链接:http://poj.org/problem?id=3320
还是运用尺取法的思路。
思路:
将头往前走,如果这个知识点没有出现过,将已有的知识点数量+1。如果覆盖了所有知识点,更新当前的最少页数。此时在判断尾巴出现的知识点是否出现超过一次,如果超过一次,那么就将尾巴往前移。因为如果没有超过一次也往前移的话,那么知识点就会少一个,导致之后头要往前移才有可能再次覆盖所有知识点,才可能再次更新。所以这其实并不一定要这样做,只有出现知识点重复的时候再将尾巴向前移动就可以。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
using namespace std;
#define M 1000000
#define INF 0x3f3f3f3f
int a[M];
int main()
{
int n;
while(scanf("%d",&n)==1)
{
map<int,int> mp;
set<int> s;
for(int i = 0;i < n;i++)
{
scanf("%d",&a[i]);
s.insert(a[i]);
mp[a[i]]++;
}
int total = s.size();
int st = 0, en = 0;
int ans = INF;
map<int,int> mp1;
int num = 0;
for(en = 0;en < n;en++)
{
if(mp1[a[en]] == 0)
num++;
mp1[a[en]]++;
while(num == total)
{
ans = min(ans,en-st+1);
if(mp1[a[st]]>1)
{
mp1[a[st]]--;
st++; //如果该知识点出现超过1次,将尾巴移动一个
}
else break;
}
}
printf("%d\n",ans);
}
return 0;
}