双指针

1. 简介

通常用于数组或字符串中进行快速查找、匹配、排序或移动操作

常见的双指针模型:

  1. 对撞指针
  2. 快慢指针

2. 对撞指针

指的是两个指针 left、right (简写为l,r) 分别指向序列第一个元素和最后一个元素。然后1指针不断递增,r不断递减,直到两个指针的值相撞或错开 (即 l >= r),或者满足其他要求的特殊条件为止。

对撞指针一般用来解决有序数组或者字符串问题 (常见于区间问题)
查找有序数组中满足某些约束条件的一组元素问题:比如二分查找、数字之和等问题
字符串反转问题:反转字符串、回文数、颠倒二进制等问题。

回文判定

#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 10;
char s[N];

int main()
{
    cin >> s + 1;
    int n = strlen(s + 1);
    int l = 1, r = n;
    bool ans = true;
    while(l < r)
    {
        if(s[l] != s[r]) ans = false;
        l ++ , r -- ;
    }

    cout << (ans ? "Y" : "N");
}

3. 快慢指针

快指针为r,慢指针为1,这样慢指针和快指针构成区间[l, r]
两个指针以不同速度、不同策略移动,直到快指针移动到数组尾端,或者两指针相交,或者满足其他特殊条件时为止。

初始状态,l一般指向a[1]r一般指向a[0],此时[1, 0]表示空区间

出循环条件:l == n 或 r == n ,或者两指针相交

美丽的区间

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
int a[N];

int main()
{
    int n, S; cin >> n >> S;
    for(int i = 1; i <= n; i ++ ) cin >> a[i];
    // ans 初始取 n + 1(不可能取到)
    int ans = n + 1;
    
    // j:快指针,i:慢指针
    for(int i = 1, j = 0, sum = 0; i <= n; i ++ )
    {
        // 若为不合法区间(i > j)或 j 有右移空间且还未达到 S : j 右移
        while(i > j || (j + 1 <= n && sum < S)) sum += a[ ++ j];
        
        // 此时区间一定合法
        if(sum >= S) ans = min(ans, j - i + 1);
        sum -= a[i];
    }
    cout << (ans > n ? 0 : ans) << endl;

    return 0;
}

挑选子串

#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 10;
int a[N];

int main()
{
    int n, m, k;
    cin >> n >> m >> k;
    for(int i = 1; i <= n; i ++ ) cin >> a[i];
    int ans = 0;
    for(int i = 1, j = 0, cnt = 0; i <= n; i ++ )
    {
        while(i > j || (j + 1 <= n && cnt < k)) cnt += (a[ ++ j] >= m);
        if(cnt >= k) ans += n - j + 1;
        cnt -= (a[i] >= m);
    }
    cout << ans << endl;

    return 0;
}

南池北塘
1 声望0 粉丝