给定一个长度为 n 的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。
输入格式
第一行包含整数 n。
第二行包含 n 个整数(均在 0∼105范围内),表示整数序列。
输出格式
共一行,包含一个整数,表示最长的不包含重复的数的连续区间的长度
数据范围
1≤n≤105
输入样例:
5
1 2 2 3 5
输出样例:
3
#include<iostream>
using namespace std;
const int N=100010;
int n;
int a[N],s[N];
int main()
{
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
int res=0;
for(int i=0,j=0;i<n;i++)
{
s[a[i]]++;
while(s[a[i]]>1)
{
s[a[j]]--;//意思就是会到第二次出现这个数的这个位置
j++;
}
res=max(res,i-j+1);
}
cout<<res<<endl;
return 0;
}
来自awing的代码
#include<iostream>
using namespace std;
const int N=100010;
int a[N],s[N];//a[N]存储n个整数
//s[N]存储每个整数出现的次数
/*
Eg:5
1 2 2 3 5
↓
s[1]=1;
s[2]=2;
s[3]=1;
s[5]=1;
对应的就是s[a[0]]=1....s[a[1]]=2
*/
int main()
{
int n;
cin>>n;
int maxl=1;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0,j=0;i<n;i++)
{
//i为右指针,j为左指针
s[a[i]]++; //记录a[i]在[i,j]间出现的次数
while(s[a[i]]>1) //当a[i]在[i,j]间出现的次数>1时,说明有元素重复了
//左指针j开始移动,当移动到重复的元素时,重复的元素的出现次数就<1了
//循环结束,这时[i,j]区间的元素恢复无重复元素状态
s[a[j++]]--; //最长的不包含重复数字的连续子序列的长度
//i-j+1就是[i,j]无重复元素区间的长度
maxl=max(maxl,i-j+1);//比较当前[i,j]无重复元素的长度与之前的maxl值,取最大
}
cout<<maxl;
return 0;
}
可能有人对下面的代码不理解,我加以叙述。
while(s[a[i]]>1)
{
s[a[j]]--;
j++;
}
一旦发现有某个数在s数组里面出现了两次,马上清除掉前面的记忆(也就是把前面所有的数从s数组里删掉,为了下一次求字符串的长度做准备,同时把指针j移动过来,最后的结果就是i和j移到了一起。并且i指针指的位置在s数组里还留有一个1,因为while的条件是s[a[i]]>1)