目录
一、基本思想
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;
}
//后面思考,如何用哈希表存储字符数组的情况
【例三】数组元素的目标和
题目描述: ![](https://img-blog.csdnimg.cn/46b00dbdced2449ba291e576db738b0f.png)
代码:
//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的子序列),则上述算法必然可以找出一个匹配