AcWing 799. 最长连续不重复子序列 *
AkariAcWing 799. 最长连续不重复子序列 - AcWing
AcWING 799. 最长连续不重复子序列 - 视频 评论区
AcWing 799. 最长连续不重复子序列 - 糖豆爸爸 - 博客园
最长连续不重复子序列 - 最清晰图解 适合新手小白食用-CSDN博客
AcWing 799. 最长连续不重复子序列 [简单] *
1 题目描述
给定一个长度为 n 的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。
输入格式
第一行包含整数 n。
第二行包含 n 个整数(均在 0 ∼ 10^5 范围内),表示整数序列。
输出格式
共一行,包含一个整数,表示最长的不包含重复的数的连续区间的长度。
数据范围
1 ≤ n ≤ 10^5
输入样例:
5
1 2 2 3 5
输出样例:
3
2 解题思路
2.1 朴素思路
for(int i = 1; i <= n; i ++ ) |
因为要执行双重循环,所以时间复杂度是 O(N^2) , 要想办法来优化它
2.2 双指针 (滑动窗口 + 桶计数)
说白了就是 : 双指针优化找单调性.
设置双指针 i 和 j, s[ ] 数组表示从 i 到 j 之间各个数字出现的次数,若
s[a[i]] > 1
则说明出现重复数字, 需要移动指针 j .res 为最长字串长度, 计算公式为
res = max(ans, i - j + 1)
|
3 Q & A
3.1 滑动窗口 + 桶计数的具路讲解
先用暴力做, 然后去看有没有单调性, 有就可以双指针优化.
维持一个窗口, 这个窗口里面保证是没有重复元素的, 窗口大小从 0 开始. 左侧有一个慢指针 j , 右侧有一个快指针 i .
当窗口中没有重复元素时, 快指针向右, 多吃进来一个.
通过桶来判断是不是有重复出现, 如果没有, 则窗口最大长度 ++ .
如果有重复元素出现, 则慢指针不断向右, 直到找出并剔除重复元素, 此时窗口变小.
在窗口快慢指针的作用下, 走完整个数组 i == n , 结束循环.
因为快慢指针只走了一遍数组, 可以视时间复杂度为 O(N), 比两层循环优化太多~
总结:
双指针, 快慢指针, 同向。
3.2 s[a[j ++ ]] -- ;
的妙处
就是把 j 所在位置的数的数量 - 1 , 然后 j ++ , j 往后移一位. s[q[i]]
存的是每个 q[i] 的数量
其实就是为寻找下一个子串要做的准备.
3.3 while 循环不需要维护 j < i
|
确实不用维护, 每次找到重复的数, 只需要收缩区间让出现次数重新变为 1 , i 不可能超过 j
3.4 res = max(res, i - j + 1);
的原因
可能 i - j + 1
会比 res
小
相当于 res 维护的是以每个 i 结尾的非重复连续序列的最大值
详细的来说就是记录之前某段连续区间的长度, 如果目前该段连续长度大于之前记录最大连续区间的长度的话就取该段为最大长度.
3.5 别人的小总结
另外图片讲解可参考:
最长连续不重复子序列 - 最清晰图解 适合新手小白食用-CSDN博客
https://blog.csdn.net/bababao_/article/details/129856751