4. 双指针算法

1.最长连续不重复子序列

给定一个长度为 n 的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。

输入格式
第一行包含整数 n。
第二行包含 n 个整数(均在 0∼105 范围内),表示整数序列。

输出格式
共一行,包含一个整数,表示最长的不包含重复的数的连续区间的长度。

数据范围
1 ≤ n ≤ 10^5
#include<iostream>
using namespace std;

const int N = 1e5 + 10;

int main() {
	int n;
	cin >> n;
	int a[N], s[N];	//s[]存储a[]中的每个数出现的次数
	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++;	//从j所在的位置开始将后面数次数依次减少直至减到i的位置,
					//将i所对应的数也减少一个后不大于一即可跳出循环,此时j更新为i的位置
		}

		res = max(res, i - j + 1);
	}

	cout << res << endl;

	return 0;
}

2. 数组元素的目标和

给定两个升序排序的有序数组 A 和 B,以及一个目标值 x。
数组下标从 0 开始。
请你求出满足 A[i]+B[j]=x 的数对 (i,j)。
数据保证有唯一解。

输入格式
第一行包含三个整数 n,m,x,分别表示 A 的长度,B 的长度以及目标值 x。
第二行包含 n 个整数,表示数组 A。
第三行包含 m 个整数,表示数组 B。

输出格式
共一行,包含两个整数 i 和 j。

数据范围
数组长度不超过 10^5。
同一数组内元素各不相同。
1 ≤ 数组元素 ≤ 10^9
#include<iostream>
using namespace std;

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

int main() {
	int n, m, x;
	cin >> n >> m >> x;

	for (int i = 0; i < n; i++)	cin >> a[i];
	for (int i = 0; i < m; i++)	cin >> b[i];

	//i从左往右走,j从右往左走
	/*
	* i从最左开始即为a[]的最小值,j从最右开始为b[]的最大值,若a[i]+b[j]还小于x的话则证明无解直接输出
	* 若有解则a[i]+b[j]一定大于x,此时j--直至满足相加小于或等于x的情况后输出
	* 小于的话跳出while循环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)	cout << i << ' ' << j << endl;
	}
	return 0;

}

3. 判断子序列

给定一个长度为 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 ≤ 10^5,
−10^9 ≤ ai,bi ≤ 10^9
#include<iostream>
using namespace std;

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

int main() {
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; i++)	cin >> a[i];
	for (int i = 0; i < m; i++)	cin >> b[i];

	//判断a是否为b的子序列
	//在进行两指针的移动时,i不动,j始终往后移直至满足条件a[i]==b[j]时将i++
	//最后再进行判断是否i==n,若是,则证明a[]中所有元素都在b[]中,满足条件
	int i;
	for (int j = 0; j < m; j++) {
		if (i < n && a[i] == b[j])	i++;	//i指向a中的数据,必须要小于a的长度n
	}

	//最后通过判断i的大小判断是否为子序列
	if (i == n)	cout << "Yes";
	else cout << "No";

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值