开始前应具备
- 掌握左右指针
- 能使用哈希表保存计数
- 理解连续子数组与子序列的区别
CHAPTER 03 · 区间建模
把子数组和子串问题转化为可维护的窗口或可快速查询的区间。
BEFORE LEARNING
子数组和子串题的核心是如何复用相邻区间的计算结果。窗口维护连续区间状态,前缀和把任意区间查询转成两个历史状态之差。
开始前应具备
完成本章后
CORE LESSONS
LESSON
题目要求所有长度恰好为 k 的连续区间,或模式串长度固定时使用。
窗口每向右移动一步,只加入一个新元素并移除一个旧元素。维护增量而不是重新统计整个区间,可把 O(nk) 降到 O(n)。
for right in range(n):
add(a[right])
if right - left + 1 > k: remove(a[left]); left += 1
if right - left + 1 == k: update()LESSON
寻找满足约束的最长或最短连续区间,且条件随窗口扩张具有可恢复的单调性时使用。
右指针负责探索新候选,左指针负责恢复合法性。最长问题通常在窗口合法时记录;最短问题通常在合法状态下持续收缩并记录。
for right in range(n):
add(right)
while need_shrink():
update_if_minimum()
remove(left); left += 1
update_if_maximum()LESSON
需要统计任意连续区间的和、数量,尤其数组包含负数而滑动窗口失效时使用。
若 prefix[j] - prefix[i] = k,则只需在扫描到 j 时查找历史上是否出现 prefix[j] - k。哈希表保存历史前缀值的次数或最早位置。
count = {0: 1}
prefix = answer = 0
for value in a:
prefix += value
answer += count.get(prefix - k, 0)
count[prefix] += 1READING
先读完本站讲义并尝试练习;遇到推导不清的地方,再回到原始教程深入阅读。
PRACTICE LADDER
题量由知识点决定,不再固定为 5 道。先完成“入门”和“模板”,再做变式与综合;挑战题可以留到复习阶段。
2 道 · 依次完成
Maximum Average Subarray I
为什么选:先掌握加入一个、移除一个的增量维护。
Find All Anagrams
为什么选:固定窗口中维护字符频率差。
3 道 · 依次完成
Longest Substring
为什么选:建立字符重复时收缩左边界的标准流程。
Minimum Size Subarray Sum
为什么选:体会最短窗口必须在合法时持续收缩。
Minimum Window Substring
为什么选:同时维护需要字符、有效字符和最小答案。
2 道 · 依次完成
Subarray Sum Equals K
为什么选:通过 prefix - k 查询历史前缀次数。
Contiguous Array
为什么选:把 0 转成 -1 后将数量平衡转成前缀相等。
PERSONAL NOTEBOOK
笔记保存在当前浏览器