双指针
1.类型
(1)两个指针指向两个序列
(2)两个指针指向一个序列
2.核心思想
3.模板
4.例题
(1)输出单词
(2)最长连续不重复子序列
双指针
1.类型
一般来说有两大类,用途广泛
(1)两个指针指向两个序列
对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作.两个序列,两个指针分别指向两个序列.
(2)两个指针指向一个序列
对于一个序列,用两个指针维护一段区间.情况更多,两个指针指向统一序列,例如 快速排序 中就用到了此类型.
2.核心思想
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
//时间复杂度为O(n^2)
}
双指针算法原本都有上述的暴力朴素算法
所以双指针算法的核心思想就是 运用某些单调的性质,将上面的朴素算法的时间复杂度O(n^2)优化到O(n)(即下面的模板)。
3.模板
(模板用来节省思考的时间)
for(i=0;j=0;i<n;i++) //i整个扫描一遍,j从某一点开始,在这假如从0开始
{ //每次i更新完之后再更新一下j
while(j<i&&check(i,j)) //j<i判断j的范围,表示j在合法的范围内; &&check(i,j)表示两数并且满足某一性质
j++;
//+每道题的具体逻辑
}
4.例题
(1)输出单词
题目描述:
给定一串有空格分开的单词,现将这些单词分别输出
输入格式
一行包含多个单词,用空格隔开。(假定第一个单词开头没有空格)
输出格式
每个单词输出一行
数据范围
1≤n≤100000
输入样例:
abc def xyz
输出样例:
abc
def
xyz
思路解析:
AC代码:
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char str[1000];
gets(str);
int n=strlen(str);
for(int i=0;i<n;i++) //i用来扫描一遍序列
{
int j=i; //j
while(j<n&&str[j]!=' ')
j++;
//下面是这道问题的具体逻辑
for(int k=i;k<j;k++)
cout<<str[k];
cout<<endl; //换行
i=j; //如果
}
return 0;
}
(2)最长连续不重复子序列
题目描述:
给定一个长度为n的整数序列,请找出最长的不包含重复数字的连续区间,输出它的长度。
输入格式
第一行包含整数n。
第二行包含n个整数(均在0~100000范围内),表示整数序列。
输出格式
共一行,包含一个整数,表示最长的不包含重复数字的连续子序列的长度。
数据范围
1≤n≤100000
输入样例:
5
1 2 2 3 5
输出样例:
3
思路解析:
AC代码:
#include <iostream>
using namespace std;
const int N=10010;
int n;
int a[N],s[N];
int main()
{
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
int res=0;
for(int i=0,j=0;i<n;i++)
{
s[a[i]]++;
while(s[a[i]]>1)
{
s[a[j]]--;
j++;
}
res=max(res,i-j+1);
}
cout<<res<<endl;
return 0;
}