判断子序列算法

双指针算法
1.j指针用来扫描整个b数组,i指针用来扫描a数组。若发现a[i] == b[j],则让i指针后移一位。
2.整个过程中,j指针不断后移,而i指针只有当匹配成功时才后移一位,若最后若i == n,则说明匹配成功。

为什么双指针做法是正确的?
整个过程中j指针不断扫描b数组并且向后移动,相当于不断给i指针所指向的a数组创建匹配的机会,只有匹配成功时i指针才会向后移动一位,当i == n时,说明全部匹配成功。

#include
#include
using namespace std;
const int N=1e5+10;
int a[N],b[N];
int main()
{
int n,m;
scanf(“%d%d”,&n,&m);
for(int i = 0;i < n; i++) scanf(“%d”,&a[i]);
for(int j = 0;j < m; j++) scanf(“%d”,&b[j]);

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

}

题目描述
给定一个长度为 n 的整数序列 a1,a2,…,an 以及一个长度为 m 的整数序列 b1,b2,…,bm。

请你判断 a 序列是否为 b 序列的子序列。

子序列指序列的一部分项按原有次序排列而得的序列,例如序列 {a1,a3,a5} 是序列 {a1,a2,a3,a4,a5} 的一个子序列。

输入格式
第一行包含两个整数 n,m。

第二行包含 n 个整数,表示 a1,a2,…,an。

第三行包含 m 个整数,表示 b1,b2,…,bm。

输出格式
如果 a 序列是 b 序列的子序列,输出一行 Yes。

否则,输出 No。

数据范围
1≤n≤m≤105,
−109≤ai,bi≤109
输入样例:
3 5
1 3 5
1 2 3 4 5
输出样例:
Yes

C++ 代码
#include
#include
#include
using namespace std;
// 新增的双指针模板题
// 基本思路就是遍历一遍“子序列” ,
// 看看其每一个元素另一个数组中是不是在都有各自的下标
// 且下标要呈递增趋势,这就有了单调性 可以用双指针
int main (){
int n,m,i,j;
scanf (“%d%d”,&n,&m);
int a[n],b[m];
for (i = 0;i < n;i++) scanf (“%d”,&a[i]);
for (j = 0;j < m;j++) scanf (“%d”,&b[j]);
i=0,j=0;
//记得复原下ij
while (i < n&&j < m){
if (a[i] == b[j]) i++;
j++;
//这个循环可理解为 对于a[i]
//b从j开始遍历 直到a[i] =b[j]了,让i+=1
//对于新的a[i],重复上行过程
//如此一来实质上就是以a[i]是否=b[j] 遍历了一遍b,注意是一遍
//期间若a[i] == b[j]了 更新ai继续遍历
}
if (i == n) printf (“Yes\n”);
//从上面的循环出来了 若a[i]遍历完了(i == n)
//就说明a是子序列 反之就不是
else printf (“No”);
return 0;
}

算法基础课笔记and题解汇总
算法基础课笔记and题解汇总

笔记:
到此双指针部分就结束啦!真开心
这题就是和归并排序一样的模式:指向两个序列的双指针算法。(其实是单指针吧。。。)
因为序列是有序的,所以我们只要从头往后扫描b数组,只要有一个a中的元素匹配不上,就是“失配”。
否则是匹配的。

代码:

#include <bits/stdc++.h>
using namespace std;
int n, m, a[100010], b[100010];
int main() {
scanf(“%d%d”, &n, &m);
for (int i = 1; i <= n; i++) scanf(“%d”, &a[i]);
for (int j = 1; j <= m; j++) scanf(“%d”, &b[j]);
int j = 1;
for (int i = 1; i <= n; i++) {
while (b[j] != a[i] && j <= m) j++;
if (j > m) {puts(“No”); return 0;}
j++;
} puts(“Yes”);
return 0;
}
1 评论

提交评论

@Chase 1个月前 回复
#include
#include
#include
using namespace std;
const int N = 1e5 + 10;
int a[N],b[N];
int n,m;

int main()
{
scanf(“%d%d”, &n, &m);
for (int i = 0; i < n; i ++ )
{
scanf(“%d”, &a[i]);
}
for (int j = 0; j < m; j ++ )
{
scanf(“%d”, &b[j]);
}
bool flag = true;
for (int i = 0,j = 0; i < n; i ++,j ++) // 相等时,i和j同步+1即可
{
while(j < m && b[j] != a[i]) j ++; // 不相等的时候:j后移找到第一个相等的
if(j == m) { // 如果未找到
cout << “No” << endl;
flag = false;
break;
}
}
if (flag)
cout << “Yes” << endl;
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值