双指针算法的一个简单题解

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;

}

若有不足之处还望指出,感谢您的浏览!



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。