给定一个长度为 n
的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。
输入格式
第一行包含整数 n
。
第二行包含 n
个整数(均在 0∼105
范围内),表示整数序列。
输出格式
共一行,包含一个整数,表示最长的不包含重复的数的连续区间的长度。
数据范围
1≤n≤105
输入样例:
5
1 2 2 3 5
输出样例:
3
双指针的一个重要的思路就是:先列举朴素的暴力做法,然后找到一个单调性做优化。实际上,双指针是在维护一段区间。
在这道题目中,朴素做法枚举i,和j,看j最大相距i有多远为本题答案。一个单调性是i和j只用往右走就可以了,因为如果红色i往右走一步,绿色还往左走的话就出现了矛盾。
(图中一个小错误是j - i + 1改成i - j + 1).
例子:
1 2 3 4 5 2 7 8 9
输出:这里根据上面那个例子打印了s数组的值,方便理解是怎么变化的。
0100000000
0110000000
0111000000
0111100000
0111110000
0121110000
XXXXXX
0121110000
while over
XXXXXX
0021110000
while over
0011110100
0011110110
0011110111
7
测试代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int a[N];
int s[N]; // 当前j到i区间里,每个数出现的次数
void out1()
{
for(int i = 0; i < 10; i ++ )
cout << s[i];
cout <<endl;
}
int main ()
{
scanf("%d", &n);
for(int i = 0; i < n; i ++ ) scanf("%d", &a[i]);
int res = 0;
for(int i = 0, j = 0; i < n; i ++ )
{
s[a[i]] ++; // 新加入一个数
out1();
while(s[a[i]] > 1)
{
cout << "XXXXXX" << endl;
out1();
s[a[j]] --;
j ++;
cout << "while over" << endl;
}
res = max(res, i - j + 1);
}
printf("%d\n", res);
return 0;
}
题解代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int a[N];
int s[N]; // 当前j到i区间里,每个数出现的次数
int main ()
{
scanf("%d", &n);
for(int i = 0; i < n; i ++ ) scanf("%d", &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);
}
printf("%d\n", res);
return 0;
}