双指针算法有时候也叫尺取法或者滑动窗口,是⼀种优化暴力枚举策略的手段:当我们发现在两层 for 循环的暴力枚举过程中,两个指针是可以不回退的,此时我们就可以利用两个指针不回退的性质来优化时间复杂度。因为双指针算法中,两个指针是朝着同一个方向移动的,因此也叫做同向双指针。
1.

#include <iostream>
#include <unordered_map>
using namespace std;
typedef long long LL;
const int N=1e6+10;
LL arr[N];
int T,n;
int main()
{
cin >> T;
while(T--)
{
unordered_map<int,int> mp;
cin >> n;
for(int i=1;i<=n;i++)
{
cin >> arr[i];
}
int left=1;
int right=1;
int ret =0;
while(right<=n)
{
mp[arr[right]]++;
while(mp[arr[right]]>1)
{
mp[arr[left]]--;
left++;
}
ret=max(ret,right-left+1);
right++;
}
cout << ret << endl;
}
return 0;
}
2.
#include <iostream>
#include <unordered_map>
using namespace std;
const int N=1e6+10;
int arr[N];
int n,m,cnt;
int L,R;
unordered_map<int,int> mp;
int main()
{
cin >> n >> m;
for(int i=1;i<=n;i++)
{
cin >> arr[i];
}
int left=1;
int right=1;
int ret=n+1;
while(right <= n)
{
mp[arr[right]]++;
if(mp[arr[right]]==1)
{
cnt++;
}
while(cnt==m)
{
mp[arr[left]]--;
if(mp[arr[left]]==0)
{
cnt--;
}
if(right-left+1<ret)
{
L=left;
R=right;
ret=right-left+1;
}
left++;
}
right++;
}
cout << L << " " << R << endl;
return 0;
}
3.
#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
const int N=1e6+10;
string s;
int cnt;
unordered_map<char,int> mp;
int main()
{
cin >> s;
int right=0;
int left=0;
int ret=N;
while(right<s.size())
{
mp[s[right]]++;
if(mp[s[right]]==1)
{
cnt++;
}
while(cnt==26)
{
ret=min(ret,right-left+1);
mp[s[left]]--;
if(mp[s[left]]==0)
{
cnt--;
}
left++;
}
right++;
}
cout << ret << endl;
return 0;
}
4.
#include <iostream>
using namespace std;
const int N=1e5+10;
int n,sum;
int arr[N];
int main()
{
cin >> n;
for(int i=1;i<=n;i++)
{
cin >> arr[i];
sum+=arr[i];
}
int left=1;
int right=1;
int ret=0,k=0;
while(right<=n)
{
k+=arr[right];
while(2*k>=sum)
{
ret=max(ret,sum-k);
k-=arr[left];
left++;
}
ret=max(ret,k);
right++;
}
cout << ret << endl;
return 0;
}