最长连续不重复子序列(双指针)
双指针算法是将双层嵌套的暴力做法优化到O(n),
for(int i=0,j=0;i//双指针板子 { while(j check(ij)) //根据题目的具体逻辑来 } 原来的模板是for的双重嵌套: for(int i=0;i ) { for(int j=0;j ) }
这里有一个双指针算法的具体典型应用:(输出单词)
#include#include using namespace std; int main(){ /*大概题意:char ch[1000]; while(cin>>ch) { cout< */ //以下为双指针算法 char ch[10000]; int len; gets(ch); len=strlen(ch); for(int i=0;i 这里是整体的大循环,虽然从过程中看不需要遍历整个i的范围,但可以用i限定在len里面 { int j=i;//下一次的输出j是从i处出发 while(j// ' ') j++;//限定j的位置 for(int k=i;k<=j;k++)//这里就相当于双指针的关键作用 cout< //先移动指针,根据指针所指确定范围来输出单词 cout<<endl; i=j;//输出下一个单词的开头就是上一个单词j的结尾,这里用i=j } return 0; }
555,怪自己的懒惰,双指针没有一气呵成的看完,断断续续,感觉掌握不是很好了,555,接着看题吧:
最长不连续子段和:
给定一个长度为
输入格式
第一行包含整数
第二行包含
输出格式
共一行,包含一个整数,表示最长的不包含重复的数的连续区间的长度。
数据范围
输入样例:
5
1 2 2 3 5
输出样例:
3
题解:双指针用法的本质是将刚刚上面发的双层嵌套的暴力优化到O(n),两个指针的关系要找好,要具有一定的单调性:
这个例子 1 2 2 3 5
刚开始指针i和j都指在1这个位置上,i在前面,j在后面。i先动,到2,j不动还是1,好没有重复元素。接下来i走到下一个2,这时候有重复元素了,j开始右移,直到与i重合
刚刚模拟的这个过程有几处需要注意,第一个i和j的移动关系,如果有重复元素,那必然是a[i],j相当于是被动的,有重复元素时j才会动,并且右移,具有单调性
第二点:话说得好听,但怎么模拟重复元素是关键。这个时候用相当于桶排的一个计数器,s[a[i]]
下面的代码就可以看清楚了,诶嘿:
#includeusing namespace std; const int N=100010; int a[N],s[N]; int main(){ int n,maxn; cin>>n; for(int i=0;i ) cin>>a[i]; for(int i=0,j=0;i ) { s[a[i]]++; while(j1) s[a[j++]]--; maxn=max(maxn,i-j+1); } cout< endl; return 0; }