双指针(Two Pointers)
简介(Introduction)
双指针算法是一种广泛运用的基础算法,在很多地方都有应用,双指针算法就是运用单调性使得指针只能单向移动。
描述(Description)
- 双指针算法是一种通过设置两个指针不断进行单向移动来解决问题的算法。
- 首先写出最朴素的两层循环的写法
- 然后考虑题目中是否具有单调性 —— 即当其中一个指针 \(i\) 向后移动时,另一个指针 \(j\) 是不是只能向着一个方向移动;如果是,则可以通过双指针算法优化。
代码(Code)
// C++ Version
for (int i = 0, j = 0; i < n; i ++ ) {
while (j < i && check(i, j)) j ++ ;
// 题目的具体逻辑
}
应用(Application)
最长连续不重复子序列
给定一个长度为 \(n\) 的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。
输入格式
第一行包含整数 \(n\) 。
第二行包含 \(n\) 个整数(均在 \(0\sim10^5\) 范围内),表示整数序列。
输出格式
共一行,包含一个整数,表示最长的不包含重复的数的连续区间的长度。
数据范围
\(1\le n \le 10^5\)
输入样例:
5
1 2 2 3 5
输出样例:
3
- 分析:
- 朴素:利用两重 \(for\) 循环暴力
- 优化:前后指针分别指向最长不重复段,前指针向后移动时,后指针也一定会向后移动。
- 题解:
// C++ Version #include <iostream> using namespace std; const int N = 1e5 + 10; int n; int a[N], s[N]; int main() { scanf("%d", &n); for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]); int res = 0; for (int i = 0, j = 0; i < n; i ++ ) { s[a[i]] ++ ; // 前指针做记录 while (s[a[i]] > 1) { // 大于 1 说明 q[i] 出现重复 s[a[j ++ ]] -- ; // 去掉重复,直到条件不成立,并同时更新 j } res = max(res, i - j + 1); // 取最长不重复区间长。 } cout << res << endl; return 0; }