滑动窗口模式
滑动窗口解决什么问题?
- 对象: 数组或字符串中的连续区间;
- 目标: 在 O(n) 时间内统计满足条件的连续区间的性质 (长度、个数、最值);
- 本质: 快慢指针的特殊形式, left 与 right 共同框出窗口;
固定长度窗口与不定长度窗口有什么区别?
| 固定长度 | 不定长度 | |
|---|---|---|
| 窗口大小 | 恒为 k | 由条件决定 |
| 扩张时机 | right 右移直到窗口满 | right 右移直到满足条件 |
| 收缩时机 | 窗口满后同步右移 left | 条件被破坏时右移 left |
| 典型问题 | 定长子数组的平均值或统计 | 最长无重复子串、最短覆盖子串 |
定长窗口的模板是什么?
left = 0
right = 0
while right < len(nums):
window.append(nums[right])
if right - left + 1 >= window_size:
维护答案
window.popleft()
left += 1
right += 1
不定长窗口的模板是什么?
left = 0
right = 0
while right < len(nums):
window.append(nums[right]) # 扩张
while 窗口需要收缩:
window.popleft() # 收缩
left += 1
right += 1
- 每个元素最多被 right 加入一次、被 left 移出一次, 总复杂度 O(n);
维护答案时要注意什么?
- 只有窗口合法时才更新答案会漏掉最后一次收缩前的状态, 需要明确更新时机;
- 求最短长度: 收缩前先更新答案, 再移动 left;
- 求最长长度: 先收缩到合法, 再更新答案;
- 无法找到答案时用哨兵值 (如
n + 1) 标记, 输出前再转换;