双指针可以把$O(n^2)$变成$O(n)$,靠的就是单调性。
单调性含义:随i的增加,j一直延一个方向变化,就是单调性。比如,随i的增加,j也一直增加,这叫单调递增,如随i的增加,j一直减小,这叫单调递减,总之随i的增加,j一会增,一会减就没有单调性了。
例题1:AcWing 799. 最长连续不重复子序列。
单调性:设[j,i]是目前的“最长不重复”,当i+1时,j也要增加。因为i增加后,如j减小了,那么组成[j-1,i+1]的新区间如果是“最长不重复”,那么上一个区间[j,i]属于[j-1,i+1],因此[j,i]就不是最长不重复,这和我们的设定有矛盾,故i增,j必增。
核心代码:
for(int i=0,j=0;i<n;i++){
s[q[i]]++;
while(s[q[i]]>1){
s[q[j]]--;
j++;
}
res=max(res,i-j+1);
}
例题2:AcWing 800. 数组元素的目标和
单调性:在A数组中i,在B数组中找到最靠左的j,使a[i]+b[j]>x成立,这时,当i增加的时候,j必然减小,因为,上一个j使得较小的i都大于x了,现在换成一个大一点的i,j必然要继续减小才能找到这样的值,符合条件。
核心代码:
for(int i=0,j=m-1;i<n;i++){
while(j>=0&&a[i]+b[j]>x) j--;
if(j>=0&&a[i]+b[j]==x) {
printf("%d %d\n",i,j);
break;
}
}
单调性好难呜呜呜呜呜呜呜呜呜呜呜