双指针算法代码模板:
for(int i=0,j=0;i<n;i++)
{
while(j<i && check(i,j)) j++;
//每道题目的具体逻辑
}
最简单的应用:输入一个字符串,输出每个单词(以空格隔开)。
int n = strlen(str);
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;
}
核心思想:
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
将上面$O(n^2)$的朴素算法优化到$O(n)$。
最长不重复子序列
暴力解法:
for(int i=0;i<n;i++)
for(int j=0;j<=i;j++)
if(check(j,i))
{
res = max(res,i-j+1);
}
优化的本质是找i和j的变化规律——单调性。
看以每个i为右端点的区间,它离得最远的左端点在什么位置
//双指针算法:O(n)
for(int i=0,j=0;i<n;i++)
{
while(j<=i && check(j,i)) j++;
res = max(res,i-j+1);
}
具体实现:
#include<iostream>
using namespace std;
int n;
const int N=100010;
int q[N],s[N];
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&q[i]);
int res=0;
for(int i=0,j=0;i<n;i++)
{
s[q[i]] ++; //记录数组中元素出现的次数
while(s[q[i]]>1)
{
s[q[j]]--; //如果q[i]=q[j],则次数减1,j往后移动
j++;
}
res = max(res,i-j+1);
}
cout<<res<<endl;
return 0;
}
加油!