Fork me on GitHub

双指针算法(尺取法)

  1. 指向两个序列
  2. 指向一个序列
    1. 维护一段区间,就像快排一样

一般的样子

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;
}
posted @ 2020-02-28 14:22  WalterJ726  阅读(116)  评论(0编辑  收藏  举报