双指针算法(尺取法)
- 指向两个序列
- 指向一个序列
- 维护一段区间,就像快排一样
一般的样子
for(i = 0, j = 0; i < n; i++)
{
while(j < i && check(i, j)) j++
// 每道题目的具体逻辑
}
最核心的性质
能优化到\(O(N)\)可能是2n,3n等等
运用了某些单调的性质
模板就是为了节省思考的时间
输出字符串
for(int i = 0; i < strlen(str); i++)
{
int j = i;
while(j < strlen(str)) j ++; // 再扫描一遍,它只会往后走
输出
}
最长连续不重复子序列
//朴素做法
for(int i = 0; i < n; i ++)
for(int j = 0; j <= i; j ++)
if(check(j, i))
{
res = max(res, j - i +1)
}
朴素算法发现一些单调性,然后改进成\(O(N)\)
//双指针
for(int i = 0; i < n; i ++)
while(j < n && check(j, i))
res = max(res, j - i)
单调队列
只要加进来的i不等于j就可以一直保证整个区间的确定性
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn = 1e5 + 10;
int a[maxn], s[maxn];
int main()
{
int n;
cin >> 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 && j <= i) // j=i的时候已经只剩下一个数字了
{
// 当右边已经不能成为一个区间的时候,就要开始移动左指针了
s[a[j]]--;
j++;
}
res = max(res, i - j + 1);
}
cout << res << endl;
return 0;
}
有什么问题可以加qq:1281372141进行交流