当前:LC107 · 二叉树的层序遍历 II · 首次出现于 Day 17 · 路径:顶栏「56天打卡」→ 点击 LC 题号 → 逐题动画

LC107 · Binary Tree Level Order Traversal II · 树 / BFS

层序遍历 II:先按 102 做,再把层序翻面

自底向上不是另一种走法。用队列一层一层取,得到从上到下的层序,最后把「层」这个数组整体反转。层内仍从左到右。

完全复用 LC102 的队列加 size 切层,得到自顶向下的层序;再把结果数组整体反转,或每层头插入结果。层内顺序不变。时间 O(n),空间 O(n)。

时间 O(n)空间 O(n)结论先行 · 全文约 6 节
导读

给你一棵二叉树的根节点,返回自底向上的层序遍历:先最深的那一层,再往上走到根,每一层内部仍然从左到右。空树返回空列表。

主例 root = [3, 9, 20, null, null, 15, 7],也就是根 3,左孩子 9,右孩子 20,20 下面再挂 15 和 7。自底向上的答案是 [[15, 7], [9, 20], [3]]。

它和 LC102 的唯一差别在最后一步:102 要 [[3], [9, 20], [15, 7]],本题把这三层整段翻转。本文要回答:队列怎样切出这三层,以及翻转的是层与层的次序,不是一层里左右的次序。

先得到自顶向下的层序

第一直觉是从叶子往上爬。可是二叉树没有父指针,站在 15 并不知道自己属于哪一层、左边还有谁。另一种错觉是深度优先先走完左子树再走右子树:同一层的 9 和 20 不会挨在一起。要按层交卷,仍然得从根开始,用队列做广度优先。

缺的不是「自底向上」这四个字,而是一张已经按层排好的表。把根放进队列。每一轮先记下当前队列长度 size,这个 size 就是这一层有多少人;只出队这么多个,把它们的值收进本层数组,同时把左右孩子接到队列尾部。size 是进本轮之前拍的快照,后面新入队的孩子属于下一层,不会被提前拿走。

用手走主例。队列先是 [3],size=1,本层收 3,把 9 和 20 入队,得到 [[3]]。下一轮 size=2,先出 9、再出 20,本层 [9, 20];9 没有孩子,20 把 15、7 入队,表变成 [[3], [9, 20]]。

再一轮 size=2,收 [15, 7],孩子没有了。演示场景里这张自顶向下的表就是 [[3], [9, 20], [15, 7]]。每个节点进出队列一次,到这里已经是 O(n)。

标准层序:[[3],[9,20],[15,7]]
3920157
结果
[3][9, 20][15, 7]
自顶向下

反转的是层,不是层里的左右

自底向上要的是叶子层在前、根层在后。已经有了 [[3], [9, 20], [15, 7]],整段反转就是 [[15, 7], [9, 20], [3]]。15 仍在 7 左边,9 仍在 20 左边——翻的是「第几层」,不是一层内部的从左到右。演示第二段标出的正是这张翻面后的表。

也可以边做边头插:每一层算完,插到结果数组最前面。这样最后不必再 Reverse,代价是数组头插可能触发搬移;链表头插或先收集再翻,效果相同。不要把每一层内部也反转,否则主例第一层会变成 [7, 15],和题目「从左到右」不符。

空树没有根,队列放不进去,直接返回空。只有一个根时,切层得到 [[根]],翻转还是它。和 102 共用同一套切层代码,最后多一行反转,面试时把差别说清楚即可。

整体反转
3920157
结果
[15, 7][9, 20][3]
反转 → [[15,7],[9,20],[3]]

Go:层序 + 反转

solution.goGo
func levelOrderBottom(root *TreeNode) [][]int {
if root == nil { return nil }
res, queue := [][]int{}, []*TreeNode{root}
for len(queue) > 0 {
size := len(queue)
level := make([]int, 0, size)
for i := 0; i < size; i++ {
n := queue[0]
queue = queue[1:]
level = append(level, n.Val)
if n.Left != nil { queue = append(queue, n.Left) }
if n.Right != nil { queue = append(queue, n.Right) }
}
res = append(res, level)
}
slices.Reverse(res)
return res
}

1空树返回 nil,不要返回含一个空层的切片。

2进入内层循环前先记下 size。主例三轮 size 分别是 1、2、2,对应 [3]、[9,20]、[15,7]。

3左孩子先入队、右孩子后入队,层内自然从左到右。最后 Reverse 只翻 res 里层的次序,15 和 7 不会对调。

总结

按 102 切出从上到下的层,再整段翻转。主例 [[15,7],[9,20],[3]]。

  • 没有父指针,不能从叶子往上爬。队列加 size 才能一层一层收。
  • 主例先得到 [[3],[9,20],[15,7]],翻面后叶子层在前。层内左右不动。
  • 头插和最后 Reverse 等价。不要把每一层内部也反转。
同族题目
LC102二叉树的层序遍历LC199二叉树的右视图LC104二叉树的最大深度