算法详解
这道题需要新学的知识一个是双指针,一个是c++库中的unordered_map容器
双指针
双指针原先我写过很多这方面的题,但是这道题我一开始是低估了它的难度,而且压根没有想到要用双指针,属于是长见识了,这道题的双指针的作用是维护一个移动窗口,这个移动窗口中没有重复的元素就可以了,至于为啥需要维护这个窗口呢?原因如下:因为可以求出整个队列中出现了多少哥不同的数字。过程如下:
至于为啥可以求出多少个不同的数字,原因是因为我们维护的这个窗口它是没有重复的元素的,当窗口中有重复的元素的时候,我们记录此时的单个元素最大值res为R-L,然后我们的左指针就会向前移动,一直到窗口周中没有重复的元素为止。等到窗口中没有重复元素(相当于我们把重复元素已经放入了res中)右指针(R)继续往前走,直达这个窗口中又有重复元素,我们只需要res=max(res,R-L)即可,这样就可以求出最大的res了。还不懂的自己动手画一画就懂了。
算法题解
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
const int N = 100010;
unordered_map<int,int> cur;
//last[i]表示下标i的上一个相同元素的下标。
int Last[N];
int main()
{
int n;
cin>>n;
int a;
//初始化Last
for(int i=0;i<n;i++){
cin>>a;
//map.count(a)在容器中查找以 key 键的键值对的个数。
if(!cur.count(a)) Last[i]=-1;
else Last[i] = cur[a];
cur[a] = i;
}
//指针就是int类型
int R=0,L=0,res=0;
//使用Last来判断窗口是否有重复的元素
//窗口是数组中下标R到L之间的区间
while(R>=L&&R<n){
//当有重复元素就停止右指针的前进,然后更新最大窗口大小
while(R<n&&Last[R]<L) R++;
res=max(R-L,res);
L++;
}
cout<<res<<endl;
return 0;
}