(双指针算法与其说是一种算法,倒不如说是一种思想:利用两个指针维护一段序列,使其中所有的数都满足某种规则)
step1:
定义两个数组:s[N] 和 a[N]
a[N] 用来记录数组的内容
(指针 i 和 j 就是用来维护数组 a 的)
s[N] 用来记录在指针 j 和 i 维护的区间内,每个数出现的次数。
step2:
起始时,指针 i 和 j 都在数组 a 的起点(i = 0,j = 0),此时 j 和 i 维护区间内的数就是 a[0],
所以 s[a[0]]++。(s[a[0]] = 1)
step3:
指针 i 继续移动,当移动到 s[a[i]] > 1时,说明在指针 j 和 i 维护的区间内,此时的 a[i](单单指 a[i] 所代表的数值) 出现了不止一次,那么就不符合要求(最长连续不重复子序列)
step4:
当出现 s[a[i]] > 1 的情况时,那么此时 j 和 i 维护的这段区间内,就说明出现了不止一次的 a[i](指数值) ,所以要开始移动指针 j ,直到指针 j 和 i 维护的区间内,没有多个相同的数
step5:
因为 s[N] 记录的是指针 j 和 i 维护的区间内每个数的出现次数,所以在移动 j 后,原先的 a[j](单指数值) 在指针 j 和 i 之间出现的次数就会减 1 ,所以:
s[a[j]]--;
j++;
不断移动 j ,直到 s[a[i]] = 1,说明此时指针 j 和 i 维护的区间内每个数都只出现了一次
step6:
用 res 记录满足最长连续不重复子序列的长度,直到 i = n-1,此时 res 所记录的就是数组 a 中最长连续不重复子序列的长度。
题目如下:
给定一个长度为 n 的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。
输入格式
第一行包含整数 n。
第二行包含 n 个整数(均在 0∼105 范围内),表示整数序列。
输出格式
共一行,包含一个整数,表示最长的不包含重复的数的连续区间的长度。
数据范围
1≤n≤105
代码如下:
#include<iostream>
#include<cstring>
using namespace std;
const int N = 100010;
int s[N];
int a[N];
int res,n;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 0;i<n;++i)
cin >> a[i];
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;
return 0;
}
(1)为什么移动指针 j 的结束条件是 s[a[i]] == 1?
模拟一遍什么都会了