这道题是AcWing y总算法基础课双指针算分的第一个应用
原题链接如下:
AcWing 799. 最长连续不重复子序列
由于本人的帖子仅仅是用于简单介绍我个人的解题思路作为我自己督促自己打卡的记录,所以不一定写得很通俗
详细题解可以看这篇:优质题解
本人代码如下:
#include<iostream>
using namespace std;
const int N = 100010;
int n;
int q[N],s[N];//s[N]是记录元素出现次数的数组,下标为元素,值为元素出现次数
int main()
{
cin>>n;
for(int i = 0;i<n;i++)scanf("%d",&q[i]);
int res = 0;
for(int i = 0,j=0;i<n;i++)
{
s[q[i]]++;
while(j<i&&s[q[i]]>1)
{
s[q[j++]] --;
}
res = max(res,i-j+1);
}
cout<<res<<endl;
return 0;
}
这里我们判断数字是否重复出现的技巧是比较巧妙的,我们开了一个s数组来记录每个数字出现的次数(原理就是一个数字重复出现的话,那个数字对应的值就是>1的),然后我们一开始先让i和j指针都指向0,然后先记录i指针指向的值出现次数+1,同时我们判断i指向的数字出现次数是否大于1,不大于1,说明这个序列暂时就是无重复数字的,我们就不会进入while循环,就会直接开始for循环下一轮,i往后移动一个单位,然后再记录i此时指向的数字出现次数+1,如果是之前已经出现过的数字,那么此时s[q[i]]
肯定就大于1了,表明此时i和j之间的序列有重复的元素,不符合条件了,所以此时我们的j需要开始往后走,j往后走一个单位,我们讨论的区间就左端点就往后移动了一个了,就不用再管j之前的元素了,所以我们需要把s数组中j指向的这个数字的出现次数-1,所以就有了s[q[j++]]--
这一行代码,++
是让j指针往后移动,--
是让j移动前指向的那个元素出现次数-1,然后一直while循环,直到又满足i到j区间内没有重复数字了,跳出while循环,记录一个结果,每次的i都会让我们记录一个结果,然后最终的结果就是求这么多个i得到的res中最大的那个,就是题解了
讲的很啰嗦,但是尽量是想用通俗的语言把整个过程给描述清楚