list.pop(0)是o(n)操作,因需移动后续所有元素;deque.popleft()是均摊o(1),适合高频队列操作,性能差距可达百倍以上。

为什么 list.append() 和 list.pop(0) 不适合高频队列操作
因为 list.pop(0) 是 O(n) 操作:Python 列表底层是动态数组,删首元素需要把后面所有元素向前平移一位。哪怕只有 1 万条数据,每秒执行 100 次 pop(0),CPU 就明显卡顿。而 deque 在两端增删都是 O(1),不挪动内存,靠双向链表+分块缓冲区实现。
deque 的正确初始化和常用操作写法
别用 deque([]) 或 deque(iterable) 做大量预填充——构造本身是 O(n),但日常使用没问题;重点是后续操作要“只碰两端”:
-
append()和appendleft():分别在右端/左端入队 -
pop()和popleft():分别从右端/左端出队 - 避免用
deque[i]随机索引访问——虽然支持,但 O(n) 时间,且说明你可能误用了 deque - 不要用
remove()或insert()——它们破坏 O(1) 保证,且易引发 IndexError
用 deque 实现滑动窗口最大值时的典型陷阱
常见错误是边遍历边调用 popleft() 却没检查索引是否越界,或忘记维护单调性。正确做法是用 deque 存下标(不是值),并确保队首始终是当前窗口内最大值的下标:
from collections import deque
def max_sliding_window(nums, k):
dq = deque()
res = []
for i in range(len(nums)):
# 移除超出窗口的下标(队首)
if dq and dq[0] == i - k:
dq.popleft()
# 从队尾弹出比 nums[i] 小的值(维持递减)
while dq and nums[dq[-1]] = k - 1:
res.append(nums[dq[0]])
return res
注意:这里 dq[0] 是合法的 O(1) 访问(deque 支持常数时间首尾索引),但 dq[1] 就是 O(n) ——别滥用。
deque 的 maxlen 参数如何防止内存无限增长
设置 maxlen 后,deque 会自动丢弃对端元素,适合做日志缓存、最近 N 条记录等场景:
-
deque(maxlen=100):超过 100 个元素时,每次append()会自动popleft() -
deque([1,2,3], maxlen=2)构造后直接变成deque([2, 3], maxlen=2),前面被截掉 - 一旦设了
maxlen,appendleft()也会触发对端淘汰,行为对称 - 但
maxlen=None(默认)时无限制;设了之后不能改,只能重建新 deque
实际部署中,忘了设 maxlen 导致 deque 持续吃内存,比算法慢更难排查。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











