python
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def levelOrder(self, root):
"""
:type root: Optional[TreeNode]
:rtype: List[List[int]]
"""
# 算法基础:队列
# 初始化结果列表,存储各层节点值
result = []
# 特殊处理:空二叉树
if not root:
return result
# 初始化队列,将根节点放入
queue = deque()
queue.append(root)
# 循环处理
while queue:
# 记录当前层节点数:实现「分层存储」的核心步骤,没有这一步,就无法区分不同层的节点。
level_size = len(queue)
# 当前层临时列表
current_level = []
# 遍历当前层所有列表
'''
关于 _(下划线变量)
在 Python 中,_ 是一个「占位符变量」,它表示:我们需要执行循环,但并不需要使用循环中的索引值(也就是不需要知道当前是第几次循环),只是单纯要循环指定次数。
'''
for _ in range(level_size):
# 取出队首节点
node = queue.popleft()
# 将当前节点的值存入临时层
current_level.append(node.val)
# 遍历当前节点的子节点
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(current_level)
return result
二叉树层序遍历(LeetCode 102)核心总结
一、题目核心要求
- 遍历规则:按「从上到下、同一层从左到右」的顺序访问二叉树节点(广度优先搜索 BFS 应用)
- 输入输出 :
- 输入:二叉树根节点
root(可能为空None) - 输出:二维列表
List[List[int]],每个子列表对应二叉树的一层节点值(如[[3], [9,20], [15,7]])
- 输入:二叉树根节点
二、核心实现原理
- 核心依赖 :
队列(Python 中用collections.deque实现),利用队列「先进先出(FIFO)」的特性,缓存下一层待处理节点,保证遍历顺序。 - 核心思想:逐层处理节点,先处理当前层所有节点,再缓存下一层节点,循环往复直到所有节点处理完毕。
- 效率保障 :
deque.popleft()时间复杂度为 O (1),比普通列表pop(0)(O (n))更高效,是实现队列的首选。
三、关键步骤(对应代码逻辑)
- 初始化 :
- 定义结果列表
result = [],用于存储分层节点值; - 特殊处理:若
root为None(空树),直接返回空列表result; - 初始化队列
queue = deque(),并将根节点root入队。
- 定义结果列表
- 核心循环(处理所有层) :
- 循环条件:
while queue(队列不为空,说明还有待处理节点); - 按层分组关键:
level_size = len(queue)(记录当前层节点数,确保只处理当前层); - 初始化当前层临时列表
current_level = [],用于存储当前层节点值; - 遍历当前层:
for _ in range(level_size)(循环level_size次,精准处理当前层所有节点):- 取出节点:
node = queue.popleft()(从队列头部取出节点,遵循 FIFO 特性); - 记录值:
current_level.append(node.val)(将当前节点值存入临时列表); - 缓存下一层:若节点有左 / 右子节点,依次将左、右子节点入队(保证下一层遍历顺序从左到右);
- 取出节点:
- 存入当前层结果:
result.append(current_level)(将当前层节点值列表加入总结果)。
- 循环条件:
- 返回结果 :循环结束后,返回
result(已按层分组的二维列表)。
四、核心代码细节解析(针对你的疑问点)
| 代码片段 | 核心意义 |
|---|---|
for _ in range(level_size) |
1. _ 是占位符,标识无需使用循环索引,仅需执行 level_size 次循环;2. 精准处理当前层所有节点,实现按层分组,避免混淆当前层和下一层。 |
node = queue.popleft() |
1. 从队列头部取出节点,遵循 FIFO 特性,保证遍历顺序;2. 取出后节点从队列中移除,避免重复处理;3. 赋值给 node 用于后续存值和取子节点操作。 |
level_size = len(queue) |
按层分组的核心,进入 while 循环时,队列中恰好是当前层所有节点,其长度即为当前层节点数。 |
queue.append(node.left/right) |
缓存下一层节点,先左后右入队,保证下一层遍历顺序仍为从左到右。 |
五、易错点提醒
- 遗漏空树处理:未判断
root is None,可能导致后续队列操作报错; - 未使用
level_size:直接在while中处理节点,无法实现按层分组,返回一维列表而非二维列表; - 使用普通列表代替
deque:list.pop(0)效率低下,数据量大时会超时; - 子节点入队顺序错误:先右后左入队会导致同层遍历顺序颠倒,不符合题目要求。
六、简洁速记口诀
- 队列初始化,根节点入队;
- 空树先返回,循环处理队;
- 记录层大小,临时存层值;
- 取出节点值,子节点入队;
- 层值入结果,最终返回之。