双指针其实不是真正的指针,而是有两个变量在序列上进行一些操作。 ——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 ;
}