一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情。
类型
- 第一类:两个指针同时指向两个序列
- 如:归并排序
- 第二类:两个指针指向一个序列
- 如:快排
模板
核心思想(性质)
- 将暴力做法(朴素算法)O(n^2)优化到O(n)
题目
思路
- 暴力做法:
- 优化做法:双指针算法O(n)
- 因为i跟j具有
**单调性关系**,都是只能向右移动- i:红颜色的箭头
- j:绿颜色的箭头
- j表示最多能向右移动多少,使得i跟j之间的不重复的数最多
check(i, j):每次判断一下i跟j之间有没有重复的元素- 怎么写?
- 因为每个整数都在[0~100000]的范围内,所以我们可以开一个数组动态地来存每个元素出现了多少次
- 如果数很大怎么办?可以用
哈希表来做 - 如果新加进来的数出现在S数组里面的值大于1,说明出现了重复的数
代码
#include <iostream>
using namespace std;
const int N = 100010;
int n; //
int a[N]; // 存的是原来的数
int s[N]; // 存的是当前j到i之间每个数出现的次数
int main()
{
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
int res = 0; // res是我们的答案
for (int i = 0, j = 0; i < n; i++)
{
// 每次加入一个数:a[i]
s[a[i]]++;
// 如果出现重复的数
while (s[a[i]] > 1)
{
s[a[j]]--;
j++;
}
res = max(res, i - j + 1); // 更新一下我们的答案
}
cout << res << endl;
return 0;
}
总结
- 如果发现有单调性,那么我们就可以考虑双指针算法来优化时间复杂度