算法学习笔记(6)——双指针算法
双指针算法
双指针算法的核心思想就是在序列上找到这样一个性质,序列上的一个指针 \(j\) 随着另一个指针 \(i\) 的移动,是单向移动的,不会发生回退,这样就能在移动指针 \(i\) 的时候去移动指针 \(j\)。由于两个指针都最多只会把序列遍历一遍,所以时间复杂度往往是从 \(O(n^2)\) 优化到 \(O(n)\) 的,也就是双指针算法能够优化掉时间复杂度上的一个维度。
双指针算法中,两个指针可能是同向移动的(类似滑动窗口),也可能是对向移动的。
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int n;
int a[N], s[N]; // a[i]保存输入的序列,s[i]记录数字i出现的次数
int main()
{
cin >> n;
for (int i = 0; i < n; i ++ ) cin >> a[i];
int res = 0;
// 从前往后遍历序列,i和j是两个指针
for (int i = 0, j = 0; i < n; i ++ ) {
// 当前遍历到的数字的出现次数加一
s[a[i]] ++;
// 如果当前数字的出现次数大于一
while (s[a[i]] > 1) {
// 从目前维护的最长子序列的头部开始删数字,直到当前数字出现次数减为1
s[a[j]] --;
// 左侧指针右移
j ++;
}
// 至此,j就是以i位置结尾的最长连续无重复子序列的最左位置,更新答案
res = max(res, i - j + 1);
}
cout << res << endl;
return 0;
}