“人类的赞歌就是勇气的赞歌。”
01
—
算法思想
对于某些遍历问题,如求一个最长连续不重复子序列,我们可以当然可以想到用一个双循环暴力求解,这导致时间复杂度是O(n²),有没有优化此类问题的解决办法呢?这就是今天介绍的双指针算法。
我们依旧以上述例子为例来讲述该算法。
若要求一个[L,R]区间内的最长连续不重复子序列,我们设定两个指针i,j,初始时i,j都指向L,若某时刻i,j位置如图所示:
如果此时[j,i]区间内没有重复元素,那么当i向右移动一次后:
有两种情况:
①[j,i]内仍然没有重复元素,那么我们可以继续移动i去寻找最长不重复序列。
②若出现了重复元素,则重复元素一定是此时i所指的元素,那么我们可以移动j,直到[j,i]内无重复元素。
无论哪种情况,我们处理完后,可以保证[j,i]没有重复元素,这样我们维护的[j,i]区间又变成了一开始的样子,就可以继续处理,整个过程只需另设一个结果变量,及时更新最长序列即可。
这样一来,我们就可以将双重循环退化为一次循环,将O(n²)的时间复杂度降到了O(n)。
02
—
代码模板
//一般模板//基本套路就是一个循环里面嵌套一个判断for(int i=0,j=0;i//i,j初始化一定要要为0 { while(check()) j++; //若通过check()函数判断出某些条件 } //则移动j指针 //对于上面讲到的求最长连续不重复子序列的求解int a[maxn];int book[maxn]; //book数组判断当前区间有无重复元素int main(){ int n; cin>>n; for(int i=0;i"%d",&a[i]); int ans=0; //ans存放结果长度 for(int i=0,j=0;i { book[a[i]]++; //第i个元素出现次数+1 while(book[a[i]] > 1) book[a[j]]--,j++; //若新进来的这个元素重复出现 //移动j指针,直到不再重复 ans=max(ans,i-j+1); //更新最后的最长区间 } cout<}