双指针算法模板

129 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

类型

image.png

  1. 第一类:两个指针同时指向两个序列
    1. 如:归并排序
  2. 第二类:两个指针指向一个序列
    1. 如:快排

模板

image.png

核心思想(性质)

image.png

  1. 将暴力做法(朴素算法)O(n^2)优化到O(n)

题目

www.acwing.com/problem/con… image.png

思路

  1. 暴力做法:
    1. image.png
  2. 优化做法:双指针算法O(n)
    1. image.png
    2. image.png
    3. 因为i跟j具有**单调性关系**,都是只能向右移动
      1. i:红颜色的箭头
      2. j:绿颜色的箭头
        1. j表示最多能向右移动多少,使得i跟j之间的不重复的数最多
    4. check(i, j):每次判断一下i跟j之间有没有重复的元素
      1. 怎么写?
      2. image.png
        1. 因为每个整数都在[0~100000]的范围内,所以我们可以开一个数组动态地来存每个元素出现了多少次
        2. 如果数很大怎么办?可以用哈希表来做
        3. 如果新加进来的数出现在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;
}

总结

  1. 如果发现有单调性,那么我们就可以考虑双指针算法来优化时间复杂度