快速排序和归并排序都是双指针算法
双指针算法,序列一定要有序
1.找出两个指针的起始位置,
2.单调性
3.移动的条件
4.移动的范围
5.大小关系
想题的时候按这几方面思考。
求单调性可以用假设法,假设i前进一位时j的前进方向
也可以用暴力解法,看i和j之间有什么单调关系。
for(int i=0,j=0;i<n;i++)
while(j<i&&check())j++||j--;
可以把时间复杂度为o(n2),转换成o(n)
这是一个两个指针都从零开始的双指针。
1.创造一个数组读入序列,然后再建造一个数组读入一个数出现了多少次,类似如桶排,然后i增大j增大
2.当出现重复元素的时候,j++,直至把重复元素剔除。
#include <iostream>
using namespace std;
const int N=1e5+10;
int a[N],b[N];
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++)cin>>a[i];
int res=0;
for(int i=0,j=0;i<n;i++){
b[a[i]]++;
while(j<i&&b[a[i]]>1)b[a[j++]]--;
res=max(res,i-j+1);
}
cout<<res;
return 0;
}
数组元素的目标和
1.这里i指针单调向右,初始尾0,范围<n,i++;
2.这里j指针单调向左,初始尾m-1,范围>=0,j--;
3.若两者和大于目标值,j--
#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 j=0;j<m;j++)cin>>b[j];
for(int i=0,j=m-1;i<n;i++){
while(j>=0&&a[i]+b[j]>x)j--;
if(j>=0&&a[i]+b[j]==x){
cout<<i<<" "<<j;
}}
return 0;
}
判断子序列
这道题和坏键盘差不多,就不细讲了
#include <iostream>
using namespace std;
const int N=1e5;
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];
int i=0;
for(int j=0;j<m;j++){
if(a[i]==b[j])i++;
}
if(n==i)puts("Yes");
else puts("No");
return 0;
}