Some Notes

Be hard-working every day.

双指针-快慢指针

双指针其实不是真正的指针,而是有两个变量在序列上进行一些操作。 ——Lqingyi(Lxandqi)

思想分类

  • 普通双指针 也就是两个普通的 for (也可以是其他的)循环嵌套。
  • 左右指针 其实就是二分搜索,一个变量指向开头,一个变量指向末尾,根据条件向中间遍历,直到指针相遇或满足某种条件。(也就是逼近答案)
  • 快慢指针 两个指针(变量)开始同时开头,但一个遍历的快,一个慢,直到条件满足或指针到末尾。

提示

双指针是二重循环。

一般来说,快慢指针的第二个指针(快指针)的变量是在 for 循环体之外定义的。因为 for 循环会初始化变量。快慢指针的变量是不可以初始化的,因为已经遍历过的就不用遍历了,再遍历一遍就变成普通双指针(暴力枚举)了。

怎么感觉只有例题才能讲清楚???

例题

给定一个长度为 的整数序列 以及一个长度为 的整数序列
请你判断 序列是否为 序列的子序列。
子序列指序列的一部分项按原有次序排列而得的序列,例如序列 是序列 的一个子序列。

输入时:
第一行包含两个整数
第二行包含 个整数,表示
第三行包含 个整数,表示
输出时:
如果 序列是 序列的子序列,输出一行 Yes
否则,输出 No

数据保证:


解题:
数据那么大,暴枚肯定不行。那么就用今天学的双指针。
一个指针 遍历数组 的元素,指针 遍历数组 的元素。写一个 while(1) 死循环, while 中每次 ++,如果 ,则 break ,如果 则输出 No 变量(指针)的定义要写在循环之外。

代码:

#include <cstdio>
using namespace std;

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