原题
题目大意: 选一段长度为 k 的区间使其包含所有元素,询问 最小 k
Input
第一行输入 一个数 n ,接下来输入 n 个数。
5
1 8 8 8 1
Output
输出最小 k .
2
解题思路:
从左往右依次取,如果不够的时候,就往右边扩
如果足够的话,就往右边缩。
用 set 记录所有不重复的元素个数。 用 map 记录是否被取过。
#include<cstdio>
#include<algorithm>
#include<set>
#include<map>
using namespace std;
const int maxn = 1000005;
set<int> se;
map<int,int> m;
int a[maxn];
int main(){
int n;
se.clear();
m.clear();
scanf("%d",&n);
for(int i = 0;i < n;i++){
scanf("%d",&a[i]);
se.insert(a[i]); // set 不重复性
}
int sum = se.size(); //sum 为不重复的元素个数
int s = 0,l = 0,r = 0;
int answer = 1000005;
while(1){
while(r < n && s < sum){
if(m[a[r]] == 0){ // 出现一次
s++; // 和加 1
}
m[a[r]]++; // map 记录 该数出现的次数
r++; // 不满足情况,右边 向右走
}
if(s < sum){
break; // 完全遍历一次,退出
}
answer = min(answer,r-l); //满足情况下的最小 数
m[a[l]]--; // map 消去它的一次记录
if(m[a[l]] == 0){ // 如果只出现了一次
s--; // 总和减一
}
l++; // 左边向右走
}
printf("%d\n",answer);
return 0;
}