c++刷题 超能力编程
视频
这道题的大意是:
在一个数组中找到最长的不重复元素的子数组。子数组是数组的一个连续部分,不重复元素是指在子数组中没有出现过的元素。
解决这个问题,我们可以采用:双指针技巧,即使用两个变量来表示一个区间。双指针技巧可以帮助我们在有序或无序的数组中快速地找到满足条件的子数组。
具体来说,我们可以使用以下这几个步骤:
定义问题:给定一个数组 q,找出其中最长的不重复元素的子数组,并输出其长度。
分析问题:我们可以观察到,如果一个子数组包含了重复元素,那么它一定不是最长的不重复元素的子数组。因此,我们需要找到一个方法来快速地排除掉包含重复元素的子数组,并保留下只包含不重复元素的子数组。
设计算法:我们可以使用两个指针 i 和 j 来维护一个只包含不重复元素的滑动窗口。指针 i 指向窗口的开始位置,j 指向窗口 结束位置。我们还需要使用一个辅助数组 s 来存储窗口中每个元素出现 次数。
编写代码:我们从左到右遍历数组中的每个元素 q[i]。对于每个元素 q[i], 我们在 s[q[i]] 中将其出现次数加一。然后我们检查 s[q[i]] 是否大于一, 这意味着 q[i] 在窗口中已经出现过了。如果是这样,我们就缩小窗口, 将 i 向前移动,直到 s[q[i]] 再次变为一。这样就保证了窗口始终只包 含不重复元素。
更新结果:然后我们更新结果,将当前窗口 长度 (i - j + 1) 和之前 最大长度 (res) 进行比较。
输出结果:最后, 打印出 res 作为答案。
评估算法: 这段代码 时间复杂度是 O(n),其中 n 是 q 的长度。空间复杂度是 O(n),其中 n 是 q 中可能出现值得范围。
代码如下:
#include<iostream>
using namespace std;
const int N = 1000010;
int n;
int a[N];
int cnt[N];
int main(){
int res = 0;
scanf("%d",&n);
for(int i = 0 ; i < n ; i ++ ) scanf("%d",&a[i]);
for(int i = 0, j = 0 ; i < n ; i ++ ){
cnt[a[i]]++;
while( cnt[a[i]] > 1 ){
cnt[a[j]]--;
j++;
}
res = max(res , i - j + 1);
}
printf("%d\n",res);
return 0;
}