双指针算法的一个简单题解
cnblogs 2024-10-12 08:39:00 阅读 95
题目是这样的:
给定一个长度为 n
的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。
输入格式
第一行包含整数 n
。
第二行包含 n
个整数(均在 0∼105
范围内),表示整数序列。
输出格式
共一行,包含一个整数,表示最长的不包含重复的数的连续区间的长度。
数据范围
1≤n≤105
输入样例:
5
1 2 2 3 5
输出样例:
3
这题用双指针算法,先介绍一下双指针算法,双指针算法最大的一个好处便是把时间复杂度从o(n**2)降低到o(n),这道题如果我们使用朴素的暴力枚举是可以做的,最好的枚举结果是
int res = 0
for(int i = 1;i <= n; i ++)
for(int j = 1;j <= i;j ++)
{
if check(i,j)//这里的函数是判断i到j之间有无重复元素
<code> continue;
else
res = max(res,i - j + 1);
}
这段代码的时间复杂度是O(n^2)。
解析:
外层循环从1到n,共执行n次。
内层循环在最坏情况下(即每次i都满足check(i, j)条件)会执行i次,因此总的执行次数为1 + 2 + ... + n = n * (n + 1) / 2,这是一个关于n的二次函数。
因此,时间复杂度为O(n^2)。
为什么双指针算法的时间复杂度是o(n)呢?
第一层循环枚举n次,但第二层的执行次数最多是n次,属于o(1)的复杂度,所以总的时间复杂度便是o(n)的复杂度。
附上本题的c++代码:
include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n;
int a[N],s[N];//a是原数组,s是统计从j到i之间每个元素出现的次数
int main()
{
int res = 0;//答案
cin >> n;
for(int i = 0;i < n;i ++)cin >> a[i];
for(int i = 0,j = 0;i < n;i ++)
{
s[a[i]] ++;
while(s[a[i]] > 1)
{
s[a[j]] --;//移动j指针,直到没有重复的元素
j ++;
}//这部分代码当这次枚举的i与上一次的重复时会执行
res = max(res , i - j + 1);
}
cout << res << endl;
return 0;
}
若有不足之处还望指出,感谢您的浏览!
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。