
双指针,或者说滑动窗口、尺取法,本质是利用枚举过程中两个指针单调移动的特性,把两层循环砍成线性。关键不是背模板,而是能看出什么时候指针不用回退。
下面通过四道典型的 OJ 题,看看同向双指针在不同场景下怎么用。
唯一的雪花

链接:唯一的雪花
暴力枚举左端点,右端点往后试探,碰到重复就停。左端点右移后,右端点其实不必回退——因为刚刚扫过的区间已经知道没有重复。于是我们就可以用两个指针维护一个窗口,哈希表记录每个数的出现次数。
- 右指针
r每进窗口就把新数的次数加一; - 如果某个数的次数超过 1,窗口不合法,这时候左指针
l向右移动,同时把离开窗口的数的次数减一,直到重新合法; - 每次窗口合法时,
r - l + 1就是当前不重复子段的长度,取最大值。
#include<iostream>
#include<unordered_map>
using namespace std;
const int N = 1e6 + 10;
int a[N];
int main(){
int t; cin >> t;
while(t--){
int n; cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
int l = 1, r = 1;
unordered_map<int,int> mp;
int ret = ;
(r <= n){
mp[a[r]]++;
(mp[a[r]] > ){
mp[a[l++]]--;
}
ret = (ret, r - l + );
r++;
}
cout << ret << endl;
}
;
}







