题目描述
思路解析动画文字版
下面 16 步动画会按主解代码推进,而不是泛泛讲题型。
1. 看输入:输入 nums = [4,2,4,5,6]。要在其中选一段连续且无重复的子数组,让和最大。注意有两个 4 是重复元素。
2. 思路:无重复滑动窗口:维护一个无重复窗口 nums[l..r]:seen 记录窗口里有哪些数,cur 记录窗口和。右端 r 每右移一格,若产生重复就从左端 l 收缩到合法。
3. r=0:取右端值 4:r=0,取右端值 x=nums[0]=4。seen 为空,4 不在 seen 中,无需收缩,直接把它纳入窗口。
4. r=0:纳入 4,更新窗口和:把 4 加入 seen,窗口和 cur = 0 + 4 = 4。当前窗口 [4] 和为 4,ans = max(0,4) = 4。
5. r=1:取右端值 2:r=1,取 x=nums[1]=2。seen={4},2 不在其中,没有重复,可直接纳入窗口。
6. r=1:纳入 2,窗口和变 6:把 2 加入 seen,cur = 4 + 2 = 6。窗口扩到 [4,2],和为 6,ans 更新为 6。
7. r=2:取右端值 4(重复!):r=2,取 x=nums[2]=4。但 4 已经在 seen 中(来自下标 0),窗口将出现重复。进入 while 循环,从左端 l 删除直到 4 不再重复。
8. 收缩:从左端删 nums[0]=4:从左端删除 nums[l=0]=4:seen 去掉 4,cur = 6 - 4 = 2,l 右移到 1。现在 seen={2},新来的 4 不再重复,退出 while。
9. r=2:纳入新的 4:把新的 4 加入 seen,cur = 2 + 4 = 6。窗口变为 [2,4](下标 1..2),和为 6,ans 仍是 6。
10. r=3:取右端值 5:r=3,取 x=nums[3]=5。seen={2,4},5 不在其中,无重复,可直接纳入。
11. r=3:纳入 5,窗口和变 11:把 5 加入 seen,cur = 6 + 5 = 11。窗口扩到 [2,4,5](下标 1..3),和为 11,ans 更新为 11。
12. r=4:取右端值 6:r=4,取 x=nums[4]=6。seen={2,4,5},6 不在其中,无重复,可直接纳入。
13. r=4:纳入 6,窗口和变 17:把 6 加入 seen,cur = 11 + 6 = 17。窗口扩到 [2,4,5,6](下标 1..4),和为 17,ans 更新为 17。
14. 遍历结束,确定最优窗口:r 已扫到数组末尾,整个过程中 ans 的最大值是 17,对应无重复窗口 [2,4,5,6](绿色)。
15. 为什么左右指针都只前进一次:关键不变量:l 与 r 都只向右单向移动,永不回头。每个元素最多进窗口一次、出窗口一次,所以总时间是 O(n)。
16. 返回答案 17:返回 ans = 17:删除子数组 [2,4,5,6] 可获得的最大得分就是 17。
记住这题的代码骨架:题意约束先落到状态变量,再用循环或递归维护它。
参考代码
class Solution: def maximumUniqueSubarray(self, nums): seen = set() l = 0 cur = 0 ans = 0 for r, x in enumerate(nums): while x in seen: seen.remove(nums[l]) cur -= nums[l] l += 1 seen.add(x) cur += x ans = max(ans, cur) return ans复杂度
- 时间复杂度:O(n),每个元素进出窗口一次
- 空间复杂度:O(n),集合保存窗口元素
易错点
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
最小覆盖子串
LeetCode 76 · 困难 · 沿着 滑动窗口套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题