题目描述
给定一个长度为n的整数序列,请找出最长的不包含重复数字的连续子序列,输出它的长度。
输入格式
第一行包含整数n。
第二行包含n个整数(均在0~100000范围内),表示整数序列。
输出格式
共一行,包含一个整数,表示最长的不包含重复数字的连续子序列的长度。
数据范围
1≤n≤100000
样例
输入样例:
5
1 2 2 3 5
输出样例:
算法1
(双指针) $O(n)$
思路
使用双指针算法,根据观察发现,当使用i,j两个快慢指针表示当前的指针移动到i的最长不重复序列时候,具有单调性,即i向后移动,j必然向右或者不动,不可能向左移动,这一单调性质导致可以使用双指针算法。
在双指针算法中,一个指针扫描整个数组而移动,关键如何找到对应的另一个指针移动的位置,在本题中,我们定义i为块指针,j为慢指针,j的位置定义为i对应的最长不重复序列的j的位置,因为不重复,i和j元素都不重复,出现次数都为一,因此我们使用一个数组s来记录各个元素出现的次数,i,j不断移动,数组及时更新,每次i更新,便更新j确保j,i区间元素都只出现一次,代码如下
C++ 代码
#include<iostream>
using namespace std;
const int N = 100010;//数据范围10w,定义为常量方便改
int n;//序列长度
int q[N],s[N];//q记录序列,s记录值出现的次数
int main(){
scanf("%d",&n);//读入序列长度
for(int i=0;i<n;i++) scanf("%d",&q[i]);//读入序列
int res = 0;//最长的长度
for(int i=0,j=0;i<n;i++){//i块指针,j慢指针,i扫描序列,j及时更新
s[q[i]]++;//q[i]这个值的出现次数++
while(j<i&&s[q[i]]>1) s[q[j++]]--;//因为i移动一次后q[i]次数大于1了,j前进直到i对应值出现次数变为1,j移动时候对应元素出现次数--
res = max(res,i-j+1);//更新最大值
}
printf("%d",res);
return 0;
}
通透,顶一顶,感觉比前面讲的好
谢谢