1.基本概念
用两个指针同时遍历区间。
其中,两个指针反向运动称为左右指针,两个指针在中间相会。
两个指针同向运动但运动速度不同,称为快慢指针,形成滑动窗口
两个指针总体只能有一个完整的循环,时间复杂度O(n)
2.滑动窗口例题
(1)一道简单一点的例题
#include <iostream>
using namespace std;
int a[100010];
int main()
{
int n, s; cin >> n >> s;
for (int i = 0; i < n; ++ i) cin >> a[i];
int sum = 0, ans = 1e8;
for (int i = 0,j = 0; i < n; ) {
if (sum < s) {sum += a[i]; i ++;} //区间和不足s,i右移寻找符合要求的区间
else {ans = min(i - j, ans); sum-= a[j]; j ++;} //该区间符合要求,比较此区间与ans中存的当前最短区间,之后j右移更新区间(是否能更短)
}//j恰好是跟在i后把全部区间遍历一遍的
if (ans == 1e8) cout << 0;//ans是初始值,即没有符合要求的区间
else cout << ans;
return 0;
}
(2)一道难一点的例题
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5+50;
int like[N];
int flag[N];
struct history {
int id, ts;
}h[N];
int cmp (history x, history y) {
return x.ts < y.ts;
}
int main()
{
int n, d, k; cin >> n >> d >> k;
for (int i = 0; i < n; i ++) scanf("%d%d", &h[i].ts, &h[i].id);
sort(h, h + n, cmp);//对点赞记录按时间排序
//代码核心部分:统计帖子有效点赞数
for (int i = 0, j = 0; i < n; i ++) { //按点赞记录顺序,遍历所有记录
like[h[i].id] ++; //对于一条点赞记录,该帖子的点赞数+1
while (h[i].ts - h[j].ts >= d) { //检查当前帖子中的失效点赞,j指向当前时间最早的那条有效点赞
like[h[j].id] --; //删去失效点赞
j ++; //j更新为后一条点赞记录
}
if (like[h[i].id] >= k) flag[h[i].id] = 1;
}
for (int i = 0; i < N; i ++) {
if (flag[i] == 1) printf("%d\n", i);
}
return 0;
}
(3)伪三指针(实质是双指针->1+2指针)
//双指针->一带二指针
#include <iostream>
#include <algorithm>
using namespace std;
int n, c;
int a[200050];
long long int sum = 0;
int main()
{
cin >> n >> c;
for (int i = 1 ; i <= n ; i++) {
cin >> a[i];
}
sort(a + 1, a + n + 1);
for (int i = 1, j = 1, k = 1; i <= n ; i++) { //多加一个指针,表示数值相同的区间
while (j <= n && a[j] - a[i] < c )
j++; //用j、k查找数字相同的区间
while (k <= n && a[k] - a[i] <= c)
k++; //区间[j,k]内所有数字相同
if (a[j] - a[i] == c && a[k - 1] - a[i] == c && k - 1 >= 1)
sum += k - j; //统计数对
}
cout << sum;
return 0;
}
代码摘自@指北针_N的博客:数据结构与算法——经典题目(5)锻造兵器
其中i遍历整个数组,j和k用于查找与a[i]距离为c的数字区间。
j 指向第一个与 a[i] 距离大于 c 的数字。 k 指向第一个与a[i] 距离大于c+1 的数字。
如果a[j] 与a[i] 的距离恰好为c,并且a[k-1](k-1 是因为k 已经超出了这个区间)与a[i] 的距离也恰好为c,那么[j, k-1] 区间内的所有数字与a[i] 的距离都恰好为c。
sum += k - j 就是计算这个区间内有多少数字与a[i] 的距离恰好为c。