刷题笔记 3| 豆包MarsCode AI 刷题

30 阅读2分钟

问题描述

小U拿到了一组排列,她想知道有多少个子区间满足区间内部的数构成一个排列。一个区间的排列是指:该区间的数包含从 1到 k 的每个数,并且每个数恰好出现一次,这个区间的长度为 kk。

例如,对于数组 [2, 1, 5, 3, 4],其中区间 [2, 2][1,2] 和 [1, 5] 都是排列。

测试样例

样例1:

输入:n = 5 ,a = [2, 1, 5, 3, 4]
输出:3

样例2:

输入:n = 5 ,a = [1, 2, 3, 4, 5]
输出:5

样例3:

输入:n = 4 ,a = [4, 3, 2, 1]
输出:4

解题思路

好的,让我们来逐步解决这个问题。首先,我们需要理解题目要求:找到所有满足条件的子区间,这些子区间内的数构成一个排列。

解题思路

  1. 理解排列的定义:一个区间内的数构成排列,意味着这个区间内的数包含从1到k的每个数,并且每个数恰好出现一次。
  2. 滑动窗口:我们可以使用滑动窗口(双指针)的方法来遍历所有可能的子区间,并检查每个区间是否满足排列的条件。
  3. 哈希表:为了快速检查区间内的数是否构成排列,我们可以使用哈希表来记录每个数出现的次数。

代码提示

以下是一些代码提示,帮助你实现这个算法:

#include <iostream>
#include <vector>
#include <unordered_map>

using namespace std;

int solution(int n, vector<int>& a) {
    int count = 0;
    unordered_map<int, int> freq; // 用于记录每个数出现的次数

    // 滑动窗口的左右指针
    int left = 0, right = 0;

    while (right < n) {
        // 将右指针指向的数加入窗口
        freq[a[right]]++;

        // 检查当前窗口是否构成排列
        while (/* 检查条件 */) {
            // 如果构成排列,增加计数
            count++;

            // 移动左指针,缩小窗口
            freq[a[left]]--;
            if (freq[a[left]] == 0) {
                freq.erase(a[left]);
            }
            left++;
        }

        // 移动右指针,扩大窗口
        right++;
    }

    return count;
}

int main() {
    vector<int> v1 = {2, 1, 5, 3, 4};
    vector<int> v2 = {1, 2, 3, 4, 5};
    vector<int> v3 = {4, 3, 2, 1};

    cout << (solution(5, v1) == 3) << endl;
    cout << (solution(5, v2) == 5) << endl;
    cout << (solution(4, v3) == 4) << endl;
    return 0;
}

解题思路

  • 一个区间内的数构成排列,意味着这个区间内的数包含从1到k的每个数,并且每个数恰好出现一次。
  • 可以使用滑动窗口(双指针)的方法来遍历所有可能的子区间,并检查每个区间是否满足排列的条件。
  • 为了快速检查区间内的数是否构成排列,我们可以使用哈希表来记录每个数出现的次数。

代码

int solution(int n, vector<int>& a) {
    int count = 0;
    for (int k = 1; k <= n; ++k) {
        for (int i = 0; i <= n - k; ++i) {
            unordered_set<int> seen;
            bool isArrangement = true;
            for (int j = i; j < i + k; ++j) {
                if (a[j] <= k && seen.find(a[j]) == seen.end()) {
                    seen.insert(a[j]);
                } else {
                    isArrangement = false;
                    break;
                }
            }
            if (isArrangement) {
                count++;
            }
        }
    }
    return count;
}