
一、双指针
双指针算法有时候也叫尺取法或者滑动窗口,是一种优化暴力枚举策略的手段: • 当我们发现在两层 for 循环的暴力枚举过程中,两个指针是可以不回退的,此时我们就可以利用两个指针不回退的性质来优化时间复杂度。 • 因为双指针算法中,两个指针是朝着同一个方向移动的,因此也叫做同向双指针。 注意:希望大家在学习该算法的时候,不要只是去记忆模板,一定要学会如何从暴力解法优化成双指针算法。不然往后遇到类似题目,你可能压根都想不到用双指针去解决。
二、双指针经典算法题
2.1 唯一的雪花
2.1.1 题目
链接:唯一的雪花

2.1.2 算法原理
我们「暴力枚举」的过程中,固定一个起点位置 left,然后之后 right 向后遍历时。当 right 第一次扫描到一个位置,使 [left,right] 这个区间「出现重复字符」,此时我们会发现:
• right 无需再向后遍历,因为继续向后走区间窗口也是「不合法」的;
• left 向后移动一格之后,right 指针也不用回退,因为我们已经维护出来 [left,right] 区间的信息,并且以 left + 1 为起点的最优解一定不会比 left 为起点的好
当我们发现暴力枚举的「两个指针不回退」时,就可以用「滑动窗口」优化:
(1)进窗口:right 位置元素记录到统计次数的哈希表中;
(2)判断:当哈希表中 right 位置的值出现超过 1 次之后,窗口内子串不合法;
(3)出窗口:让 left 所指位置的元素在哈希表中的次数减一;
(4)更新结果:判断结束之后,窗口合法,此时更新窗口的大小。
技巧:(1)哈希表可以使用 STL 或者使用数组模拟一个哈希效果(2)依照题意可能在判断条件内也可能在判断条件外
2.1.3 代码
#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;
( i = ; i <= n; i++) cin >> a[i];
l = , r = ;
unordered_map<,> mp;
ret = ;
(r <= n){
mp[a[r]]++;
(mp[a[r]] > )
mp[a[l++]]--;
ret = (ret, r - l + );
r++;
}
cout << ret << endl;
}
;
}






