用collections.deque实现层序遍历,需冻结每层队列长度并检查空节点;list.pop(0)为O(n)操作,deque.popleft()才是O(1)。

用 collections.deque 做队列,别用 list.pop(0)
层序遍历本质是 BFS,必须保证先进先出;用 list 模拟队列时调用 pop(0) 是 O(n) 操作,树一深就明显卡顿。Python 标准库的 deque 才是真·O(1) 出队。
常见错误现象:list.pop(0) 在千级节点时耗时跳变,本地跑得动,线上一压测就超时。
- 导入写
from collections import deque,不是import collections - 初始化队列:用
deque([root]),别漏中括号 —— 单个节点也要包成可迭代对象 - 出队统一用
q.popleft(),入队用q.append()
while q: 循环里怎么分层?用 len(q) 冻结当前层长度
不分层的话,输出就是扁平一串;要按层输出(比如返回 [[3], [9, 20], [15, 7]]),关键在每次进入 while 循环时,立刻记下当前队列长度,它代表「本层有多少节点待处理」。
容易踩的坑:在循环里边 pop 边 len(q),结果长度动态变,导致某层节点被错分到下一层。
立即学习“Python免费学习笔记(深入)”;
- 写法固定:开头
level_size = len(q),然后for _ in range(level_size): - 这个
for循环里只处理本层节点,子节点全 append 到队尾,不影响level_size - 如果只要求打印每层末尾节点(如右视图),就在
for最后一次迭代时记录
空节点怎么处理?if node is None: continue 要写在循环体开头
二叉树输入常含 None(比如 LeetCode 的 [3,9,20,null,null,15,7] 序列化结果),不做检查会导致 AttributeError: 'NoneType' object has no attribute 'left'。
典型错误场景:建树时把 None 放进了队列,后续直接访问 node.left 爆错。
- 每次
popleft()后第一件事:加if node is None: continue - 子节点入队前也得判空:
if node.left: q.append(node.left),不能无脑q.append(node.left) - 不建议用
try/except AttributeError捕获——掩盖逻辑问题,且慢
LeetCode 102 题标准模板长这样
这是能直接粘贴、通过、不改结构就能复用的最小可行代码。注意缩进和空节点防护已嵌入:
from collections import deque
def levelOrder(root):
if not root:
return []
q = deque([root])
res = []
while q:
level_size = len(q)
level_nodes = []
for _ in range(level_size):
node = q.popleft()
if node is None:
continue
level_nodes.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
res.append(level_nodes)
return res
真正难的不是写出来,是记住每次进 for 循环前 freeze 队列长度、以及每个 node 访问前做 is None 检查——这两处漏掉一个,调试半小时起步。


















