暴力法用max()遍历每个窗口,时间复杂度O(nk),当n=10⁵、k=10⁴时达10⁹量级,必然超时;单调队列通过维护递减下标序列,使每个元素最多入队出队一次,总复杂度降为O(n)。

为什么直接用 max() 遍历窗口会超时
滑动窗口最大值问题中,如果对每个窗口都调用 max(window),时间复杂度是 O(nk),当 n=10⁵、k=10⁴ 时必然 TLE。关键不是“怎么写”,而是“怎么避免重复比较”——单调队列正是为这个设计的:它维护一个从队首到队尾严格递减的下标序列,保证队首永远是当前窗口的最大值下标。
deque 存下标而非数值,且必须存下标
存下标才能判断队首是否还在窗口内(用 i - k + 1 比较),也方便后续取值;存数值会导致无法判断过期。Python 中用 collections.deque,但注意所有操作都针对下标:
- 入队前,从队尾弹出所有
nums[deque[-1]] 的下标(维持递减) - 队首若
,说明已滑出窗口,必须popleft() - 窗口成型后(
i >= k - 1),nums[deque[0]]就是答案
边界处理:k=1 或空数组必须提前 return
这类题常有极端 case:k == 1 时每个元素都是自己的最大值;nums 为空或 k > len(nums) 时应返回空列表。不加判断会导致 deque 访问越界或逻辑错乱。实际写法中,建议在开头就加:
if not nums or k == 0 or k > len(nums):
return []
为什么不能用 list 模拟 deque
list.pop(0) 是 O(n) 操作,而 deque.popleft() 是 O(1)。在窗口频繁滑动时,用 list 会让整体退化成 O(nk)。另外,deque 支持 append()、pop()、popleft() 全部 O(1),是唯一满足单调队列性能要求的内置结构。
单调队列真正难的不是写法,而是理解“下标有效性检查”和“递减性维护”的先后顺序——必须先清队尾再清队首,否则可能把刚入队却已过期的下标漏掉。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











