双指针算法总结

双指针算法分为两类:第一类指向一个序列(更多的情况),第二类指向两个序列。

基本的代码框架是:

for (i = 0, j = 0; i < n; i++)
{
    while (j < i && check(i, j)) j++;
    
    // 每道题目的具体逻辑
}

核心思想:运用单调性等性质,将O(n2)的算法优化到O(n)。

种类:快排的划分、归并排序的归并、KMP算法等。

 

第一类:指向一个序列

题目链接:

https://www.acwing.com/problem/content/801/

题解:

遍历区间,对于每一个i,找到最左边的j,使得[j, i]区间中的数不包含重复元素。满足单调性,可以使用双指针算法。

代码:

#include <iostream>

using namespace std;

const int N = 100010;

int n;
int a[N], s[N];

int main()
{
    cin >> n;
    for (int i = 0; i < n; i++) cin >> a[i];
    
    int res = 0;
    for (int i = 0, j = 0; i < n; i++)
    {
        s[a[i]]++;
        while (s[a[i]] > 1)
        {
            s[a[j]]--;
            j++;
        }
        
        res = max(res, i - j + 1);
    }
    
    cout << res << endl;
    
    return 0;
}

 

第二类:指向两个序列

题目链接:

https://www.acwing.com/problem/content/802/

题解:

对于有序数组中的每一个数A[i],在B数组中找到最左边的数B[j],使得A[i] + B[j] >= x。基于这一思想,i从1到n遍历,j从m - 1到0遍历,利用单调性,使用双指针算法,找到第一个满足条件A[i] + B[j] == x的数对即可。

代码:

#include <iostream>

using namespace std;

const int N = 100010;

int n, m, x;
int a[N], b[N];

int main()
{
    scanf("%d%d%d", &n, &m, &x);
    for (int i = 0; i < n; i++) scanf("%d", &a[i]);
    for (int i = 0; i < m; i++) scanf("%d", &b[i]);
    
    for (int i = 0, j = m - 1; i < n; i++)
    {
        while (j >= 0 && a[i] + b[j] > x) j--;
        if (a[i] + b[j] == x)
        {
            printf("%d %d\n", i, j);
            break;
        }
    }
    
    return 0;
}

补充题目链接:

https://www.acwing.com/problem/content/2818/

题解:

从左到右遍历a序列,从b序列中找到与a序列相等的数字,找到所有a序列的匹配,则可以输出Yes,否则输出No。

代码:

#include <iostream>

using namespace std;

const int N = 100010;

int n, m;
int a[N], b[N];

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i++) scanf("%d", &a[i]);
    for (int i = 0; i < m; i++) scanf("%d", &b[i]);
    
    int i = 0, j = 0;
    while (i < n && j < m)
    {
        if (a[i] == b[j]) i++;
        j++;
    }
    
    if (i == n) puts("Yes");
    else puts("No");
    
    return 0;
}

 

posted @ 2023-11-30 22:31  ykycode  阅读(44)  评论(0编辑  收藏  举报