题目链接:
http://poj.org/problem?id=3320
题目大意:
给一个数列,找一个最小的区间,使得区间里面能够包含原数列中出现的所有数。
思路:
尺取法。所谓的“尺取法”,就是维护两个指针,指向当前维护的区间的首和尾。维护是贪心的去尽量的缩小区间范围。
这道题目就是要保证首指针指向的数只需要出现一次,否则就将首指针向后移动。如果现在区间里面的数小于需要的数,就将尾指针往后移动。
代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#define M 1000005
int a[M];
using namespace std;
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
int n,i,j,k,sizes,x,t,maxi;
set<int>st;
map<int,int>mp;
while(scanf("%d",&n)!=EOF)
{
t=0;maxi=99999999;
st.clear();
mp.clear();
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
st.insert(a[i]);
}
sizes=st.size();
int l,r;
l=r=1;
x=r-l+1;
mp[a[1]]=1;
t=1;
for(i=2;i<=n;i++)
{
r=i;
if(mp[a[i]]==0){t++;}
mp[a[i]]++;
if(a[i]==a[l]){
while(mp[a[l]]>1){
mp[a[l]]--;
l++;
}
}
if(t==sizes){
x=r-l+1;
//printf("%d %d %d %d\n",l,r,x,i);
if(x<maxi)maxi=x;
}
}
printf("%d\n",maxi);
}
}
/*
7
2 3 4 2 2 3 4
6
2 4 3 4 2 8
6
2 4 4 3 4 2
*/