用二分查找的思路
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int n,m;
//定义数组大小
const int N=1e5+10;
// 定义数组 a 和 cnt. a 用于存储输入的数据,cnt 用于存储每个数字出现的次数
int a[N];
int cnt[1010];
// 定义函数 check,用于检查长度为 len 的子序列是否包含 m 个新元素
bool check(int len)
{
// 初始化 cnt 数组为 0
memset(cnt,0,sizeof(cnt));
// 初始化 k 为 0,用于记录新元素个数
int k=0;
// 遍历长度为 len 的子序列
for(int i=1;i<=len;i++)
{
// 统计当前元素在子序列中出现的次数
cnt[a[i]]++;
// 如果当前元素在子序列中第一次出现(即之前没有出现过)
if(cnt[a[i]]==1)
// 新元素个数 k 加一
k++;
// 如果新元素个数 k 等于目标值 m,说明长度为 len 的子序列中包含了 m 个新元素,返回 true
if(k==m) return true;
}
for(int i=1;i+len<=n;i++){
// l 为左端点,r 为右端点,初始值均为 i(即子序列的第一个元素)
int l=i;
int r=i+len;
// 如果左端点和右端点对应的元素相等,则继续循环(因为已经包含在之前的遍历中了)
if(a[l]==a[r]) continue; //如果找到了就不再--
cnt[a[l]]--;
// 对于右端点 a[r],其对应的新元素个数加一(因为新加入了一个新元素)
if(cnt[a[l]]==0) k--;
cnt[a[r]]++;
// 如果右端点 a[r] 的新元素个数变为 1,说明其是新元素,新元素个数 k 加一
if(cnt[a[r]]==1) k++;
// 如果新元素个数 k 等于目标值 m,说明长度为 len 的子序列中包含了 m 个新元素,返回 true
if(k==m) return true;
}
return false;
}
int main()
{
//请在此输入您的代码
//关闭同步输入流;
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;//输入数据的个数
m=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(cnt[a[i]]==0)m++;//i为0说明里面没有数据
cnt[a[i]]++;
}
//开始二分查找
int l=m,r=n;
while(l<r)
{
int mid=(l+r)>>1;
if(check(mid))
{
r= mid; // //将搜索范围缩小为右半部分
}
else
{
l=mid+1; //将搜索范围缩小为左半部分
}
} cout<<l<<endl;
return 0;
}