标准答案
- 用计数器、总和或集合维护当前窗口状态。
- 右指针加入新元素后,如果窗口不合法,就不断移动左指针并撤销对应状态。
- 在窗口合法时更新答案;收缩条件必须与题目约束完全对应。
题目解析
滑动窗口的前提是右指针扩展后,违反约束时可以通过移动左指针恢复合法,并且左右指针都只向前移动。计数器、总和或集合要随着元素进入和离开同步更新。
窗口合法时更新答案,收缩条件要严格对应题目约束。例如无重复子串要移除到重复字符消失,不能只移动一次。每个元素最多进出一次时,时间复杂度通常是 O(n)。
如果窗口状态不能单调恢复,例如负数导致“和至少为 target”的条件不再单调,就不能机械套模板,需要前缀和、单调队列或其他算法。
代码示例
以无重复字符最长子串为例:
TypeScript
let left = 0, best = 0
const seen = new Set<string>()
for (let right = 0; right < text.length; right++) {
while (seen.has(text[right])) seen.delete(text[left++])
seen.add(text[right])
best = Math.max(best, right - left + 1)
}常见误区
- 误区:窗口收缩后不删除对应状态。改正:左指针每移动一次,都要撤销计数、总和或集合记录。
- 误区:窗口仍不合法时更新答案。改正:先恢复约束,再根据题意更新最大或最小窗口。
- 误区:所有连续子数组问题都套滑动窗口。改正:先判断约束是否单调,不能满足时改用前缀和、堆或其他方法。