算法基础课--双指针

94 阅读2分钟

1 模板

for (int i = 0, j = 0; i < n; i ++ )
{
    while (j < i && check(i, j)) j ++ ;

    // 具体问题的逻辑
}
常见问题分类:
    (1) 对于一个序列,用两个指针维护一段区间
    (2) 对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作

2 例题

2.1 例题一

最长连续不重复子序列

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

输入格式

第一行包含整数 nn

第二行包含 nn 个整数(均在 01050 \sim 10^5 范围内),表示整数序列。

输出格式

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

数据范围

1n1051 \le n \le 10^5

输入样例:

5
1 2 2 3 5

输出样例:

3

题解

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n; 
int a[100010],s[100010];//s[i]是从j到i中的每一个数是否出现 

int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	int res=0;
	for(int i=1,j=1;i<=n;i++){
		s[a[i]]++; 
		while(j<i && s[a[i]]>1){
			s[a[j]]--;
			j++;
		} 
		res=max(res,i-j+1);
	}
	cout<<res;
	
	return 0;
}

2.2 例题二

www.acwing.com/problem/con…

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

输入格式

第一行包含整数 nn

第二行包含 nn 个整数(均在 01050 \sim 10^5 范围内),表示整数序列。

输出格式

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

数据范围

1n1051 \le n \le 10^5

输入样例:

5
1 2 2 3 5

输出样例:

3

题解

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,x; 
int a[100010],b[100010];

int main(){
	cin>>n>>m>>x;
	for(int i=0;i<n;i++) cin>>a[i];
	for(int i=0;i<m;i++) cin>>b[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;
	}
	return 0;
}

2.3 例题三

www.acwing.com/activity/co… 给定一个长度为 nn 的整数序列 a1,a2,,ana_1,a_2,…,a_n 以及一个长度为 mm 的整数序列 b1,b2,,bmb_1,b_2,…,b_m

请你判断 aa 序列是否为 bb 序列的子序列。

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

输入格式

第一行包含两个整数 n,mn,m

第二行包含 nn 个整数,表示 a1,a2,,ana_1,a_2,…,a_n

第三行包含 mm 个整数,表示 b1,b2,,bmb_1,b_2,…,b_m

输出格式

如果 aa 序列是 bb 序列的子序列,输出一行 Yes

否则,输出 No

数据范围

1nm1051 \le n \le m \le 10^5,
109ai,bi109-10^9 \le a_i,b_i \le 10^9

输入样例:

3 5
1 3 5
1 2 3 4 5

输出样例:

Yes
#include <bits/stdc++.h>
using namespace std;
int n,m;
int a[100010],b[100010];


int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=m;i++) cin>>b[i];
	
	int i=1,j=1;
	while(i<=n&&j<=m){
		if(a[i]==b[j]) i++;
				j++;
	}
	if(i==n+1) cout<<"Yes";
	else cout<<"No";

	return 0;
}