【学习算法】双指针算法

目录

一、基本思想

     1、双指针算法的类型 

​     2、核心思想

     3、 基本写法    ​

二、经典例题

【例一】

【例二】最长连续不重复子序列

【例三】数组元素的目标和

【例四】判断子序列

一、基本思想

     1、双指针算法的类型 

        (1) 指针在两个序列中,一个指针指向其中一个序列,另外一个指针指向另外一个序列,如归并排序;

        (2) 两个指针指向同一个序列,如快排,一个指针指向开头,另一个指针指向结尾,两个指针实际上维护的是一段区间;

     2、核心思想

        可以将如下O(n^2)的算法优化到 O(n);

        for(int i=0;i<n;i++)

                for(int j=0;j<n;j++)

     3、 基本写法    

二、经典例题

【例一】

  题目描述:

          输入一个字符串,其中包含的单词是用空格隔开的,将其中包含的单词输出。

          输 入:“abc def ghi”,输出:“abc”、“def”、“ghi”,每个单词占一行。

  代码:

#include<bits/stdc++.h>
using namespace std;

int main()
{
	char str[1000];
	gets(str);   //输入字符串 
	
	int n=strlen(str);  //定义一个n表示字符串长度 
	for(int i=0;i<n;i++)
	{
		int j=i;
		while(j<n&&str[j]!=' ') 
		{
			j++;
		} 
		for(int k=i;k<j;k++) //输出当前这个单词 
			cout<<str[k];
		cout<<endl;
		
		i=j;  //i越过这个单词,继续下一个单词 
	}
	return 0;
}

【例二】最长连续不重复子序列

  题目描述:

  代码:

#include<bits/stdc++.h>
using namespace std;
const int N=100010;

int n;
int a[N]; 
int s[N]; //存入当前j~i这个区间里每个数出现的次数 

int main()
{
	scanf("%d",&n);
	for(int i=0;i<n;i++) scanf("%d",&a[i]);
	
	int res;//表示结果 
	for(int i=0,j=0;i<n;i++)
	{
		s[a[i]]++; 
		while(j<=i&&s[a[i]]>1) 
		{
			s[a[j]]--; //这个数摘除满足条件的区间 
			j++;
		}
		res=max(res,i-j+1);	
	}
	printf("%d",res);
	return 0;
}


//后面思考,如何用哈希表存储字符数组的情况

【例三】数组元素的目标和

  题目描述: 

  代码:

//i从0开始,j从最大开始  
#include<bits/stdc++.h>
using namespace std;
const int N=100010;

int n,m,x;
int a[N];
int b[N];
int res1,res2;

int main()
{
	scanf("%d%d%d",&n,&m,&x);
	for(int i=0;i<n;i++) scanf("%d",&a[i]);
	for(int j=0;j<m;j++) scanf("%d",&b[j]);
	
	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)
		{
			res1=i;
			res2=j;
		}
	}
	printf("%d %d",res1,res2);
	return 0;
}

【例四】判断子序列

  题目描述:

  代码:

#include<bits/stdc++.h>
using namespace std;
const int N=100010;

int n,m;
int a[N];
int b[N];

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++) scanf("%d",&a[i]);
	for(int i=0;i<m;i++) scanf("%d",&b[i]);
	
	int i,j;
	for(i=0,j=0;i<m;i++) //从前往后扫描数组b 
	{
		while(j<n&&a[j]==b[i]) //找到相同的 
		{
			j++;
			break;
		}
	}
	if(j==n) //当扫描完后,发现a数组都顺次找到和他匹配的数就输出YES 
		printf("Yes");
	else
		printf("No"); 
	return 0;
}

//双指针做法可以找到匹配方式
//若存在一种匹配(存在一个b的子序列),则上述算法必然可以找出一个匹配 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值