最长连续不重复子序列
这是一道基于双指针算法的题目,但是想解这道题需要一点额外的思路,第一遍我没想出来,故在此对这道题的思路进行记录。
题目描述与输入输出
思路
这道题目的要求是寻找不包含重复的数的最长子序列,从题目来看可以使用双指针算法来进行求解,使用 i i i指针向后遍历,使用 j j j指针记录合法的区间起点。
问题的难题在于如何对子序列中重复的数进行判断,即判断当前子序列是否满足题目条件。
正确的解决办法是使用另一个数组 s s s来记录子序列中数字出现的次数,它的角色有点像map,但由于题目描述中提到数字的大小不会大于 1 0 5 10^5 105,因此直接使用另一个数组来存储该信息即可。
具体来说,以 1 1 1作为数组的下标起点,初始化两个指针,使i=1, j=1
,在每一次迭代的过程中都使i++
,并使得s[a[i]] ++
,这里的 a a a数组是存储完整序列的数组,s[a[i]] ++
的含义是使a[i]
这个数在子序列的出现次数加一。
之后使用while循环来对 j j j指针进行移动,如果s[a[j]] > 1
,则说明a[j]
这个数在子序列中出现了超过两次,需要将 j j j指针右移,因为包含当前位置的子序列已经不满足“不重复”这条性质,持续地对s[a[j]]
进行判断直到满足子序列的条件,停止 j j j指针的移动。
此时,使用 r e s res res来对答案进行记录,使得res = max(res, i-j+1)
。
最后输出 r e s res res就是最终答案。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;const int maxn = 1e5 + 5;
int a[maxn] = {0};
int s[maxn] = {0};
int n;int main()
{ios::sync_with_stdio(false);cin.tie(0);cin >> n;for(int i=1; i<=n; i++) {cin >> a[i];}int res = 0;for(int i=1, j=1; 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;
}