
前言
本专栏聚焦算法题实战,系统讲解算法模块。以《C++ 编程》《数据结构与算法》等板块为基础,通过题目带点,讲解思路与代码实现,帮助大家快速提升代码能力。
一、双指针
双指针算法有时也被称为尺取法或滑动窗口,本质上是一种优化暴力枚举的策略。
当我们发现两层 for 循环的暴力枚举过程中,两个指针是可以不回退的,就可以利用这一性质来优化时间复杂度。因为双指针算法中,两个指针通常朝着同一个方向移动,所以也叫同向双指针。
学习时切忌死记模板,关键在于理解如何从暴力解法演进到双指针。否则遇到类似题目,可能很难想到用双指针去解决。
二、双指针经典算法题
2.1 唯一的雪花
2.1.1 题目
链接:唯一的雪花

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







