滑动窗口需维护有序性时不用list因pop(0)为o(n),而deque两端操作均为o(1);但deque随机访问为o(n),求中位数等需换结构;标准写法是手动控制长度:append后判断len>k则popleft;求最大值宜用单调递减deque,队首即最大值;maxlen参数虽简但隐藏删除逻辑,调试困难,生产环境建议显式控制。

滑动窗口需要维护有序性时,为什么不能直接用 list?
因为 list 的 pop(0) 是 O(n) 操作,窗口每滑动一次都要整体前移,数据量大时会明显拖慢。而 deque 的两端增删都是 O(1),天然适配「进一个、出一个」的滑动模式。
但要注意:如果窗口内需频繁按索引查值(比如取中位数),deque 的随机访问仍是 O(n),这时得换结构——别硬扛。
用 deque 实现固定长度滑动窗口的标准写法
核心是控制长度:每次 append 新元素后,检查长度是否超限,超了就 popleft。
- 初始化:
from collections import deque;window = deque(maxlen=k)是最简方式,但会自动丢弃旧值,无法触发自定义逻辑(比如记录最大值) - 手动控制更灵活:
window = deque(),然后在循环里window.append(x)后加if len(window) > k: window.popleft() - 注意:不要用
window.pop()替代popleft(),那会删错端——滑动窗口必须删左端旧值
窗口内求最大值?别存全部值,用单调 deque
如果只是要每个窗口的最大值,存所有数是浪费。用单调递减 deque,队首始终是当前窗口最大值。
关键操作逻辑:
- 入队前,从队尾开始弹出所有
的值(维持递减) - 入队
x - 检查队首是否已滑出窗口(可用下标或存 (value, index) 元组)
- 窗口成型后(
len(window) == k),队首就是答案
示例片段:
for i, x in enumerate(nums):<br> while window and window[-1] window.pop()<br> window.append(x)<br> if i >= k - 1:<br> result.append(window[0])<br> if window[0] == nums[i - k + 1]:<br> window.popleft()
maxlen 参数看似方便,但容易掩盖边界问题
deque(maxlen=k) 会在满时自动删左端,省代码但藏坑:
- 你无法在删除发生前做任何事(比如更新哈希统计、触发回调)
- 当
k == 0或输入为空时,maxlen行为可能不符合预期,不如显式控制清晰 - 调试时看不到「删了谁」,出问题难定位——尤其多线程或状态依赖场景
真要图省事,只在原型验证或纯计算场景用 maxlen;上线代码建议手写 popleft 判断。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











