双指针可以用于维护两个序列或者一个序列
双指针算法用来把暴力算法的两重遍历进行优化,减小时间复杂度
从两重遍历中找到在上一次遍历中可以优化跳过的部分,j就可以不用再从头开始
O(n^2)——>O(2n)
不好怎么用语言描述看题吧
799.最长连续不重复子序列
朴素做法:用i枚举终点,j遍历(0,i)之间最长的连续不重复子序列;这样做的复杂度是O(n^2)
双指针优化:每次i往后移动一次,此时i对应的j,一定会在i-1对应的j的后面,那么每次j就不用回到0了可以从上次的j继续进行判断扫描;
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100010;
int a[N],s[N];
int n,res;
int main()
{
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0,j=0;i<n;i++)
{
s[a[i]]++; //a[i]出现的次数++
while(s[a[i]]>1)
{
s[a[j]]--;
j--;
}
res=max(res,i-j+1);
}
cout<<res;
}
800.数组元素的目标和
朴素做法:对于每个i都遍历一遍j看是否=x
双指针:思考是否上一次的i对应的j可以对这一次的i的j的定位起到影响,
可以想到j从b数组最后一个数开始遍历(即从b数组中的最大数开始)如果上一次的a[i]+b[j]
都大于了x
而 a[i+1]>a[i]
那么a[i+1]+b[j]
也一定会大于目标元素.可以知道就只需要遍历上次的j的前面的数即(0,1,2,3..j)
#include<iostream>
using namespace std;
const int N=100010;
int a[N],b[N]
int n,m,x;
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(a[i]+b[j]>x) j--;
if(a[i]+b[j]==x) cout<<i<<" "<<j;
}
}