title: 双指针算法
date: 2019-05-26 23:45:09
tags: 双指针算法
双指针算法
主要是两大类:
模板:
for(i=0,j=0;i<n;i++)
{
while(j<i&&check(i,j))
j++;
//每道题目的具体逻辑
}
核心思想:
将一个
O
(
n
2
)
O(n^2)
O(n2) 的算法 优化成
O
(
n
)
O(n)
O(n)的
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
-->
for(i=0,j=0;i<n;i++)
{
while(j<i&&check(i,j))//看似依然是两重循环,但是i,j移动的距离最多为n,所以总共最多为2n
j++;
//每道题目的具体逻辑
}
eg:
输入:
abc deg gh
输出:
abc
deg
gh
#include <iostream>
#include <cstring>
const int maxn=1e3+5;
using namespace std;
int main()
{
//string s;
//cin>>s; 注意string是以空格停止读入的
//cout<<s<<endl;
char s[maxn];
gets(s);
for(int i=0;i<strlen(s);)
{
int j=i;
while(j<strlen(s)&&s[j]!=' ')
j++;//j总是指向一个单词结束之后的那个位置
for(int k=i;k<j;k++)
cout<<s[k];
cout<<endl;
i=j+1;
}
return 0;
}
应用:快排的划分,归并的归并部分,KMP算法等
一般都能够先想出一个 O ( n 2 ) O(n^2) O(n2) 朴素做法,然后可以改用双指针
例题:
给定一个长度为n(<1e5)的整数序列,请找出最长的不包含重复数字的连续区间,输出它的长度。
输入:
5
1 2 2 3 5
输出:
3
注意到这个单调性(具体表现为j++),并进行优化,是本题关键
所有本题 可以用单调队列来做,如果范围很大,不能直接开那么大的数组,可以用哈希表
#include <iostream>
#include <cstring>
const int maxn=1e5+5;
using namespace std;
int cnt[maxn],a[maxn];//cnt用于动态的记录当前区间内a[i]的个数
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++)
{
cnt[a[i]]++;//i指向右端点,j指向左端点
while(cnt[a[i]]>1)//说明区间内有重复元素,注意 这里是a[i]
{ //j是随着i往右移的
cnt[a[j]]--;
j++;
}
res=max(res,i-j+1);
}
cout<<res<<endl;
return 0;
}
此时 cnt[a[i]]=2