在问 · 算法题解

107. 二叉树的层序遍历 II

中等二叉树广度优先搜索 + 反转力扣原题 ↗

题目描述

输入二叉树的根节点 root。按层收集节点值,但层的输出顺序要反过来:最深的一层排在最前面,根所在的那一层排在最后。

每一层内部仍然按从左往右的次序排列。

返回这些层组成的列表。空树返回 []。树用层序数组表示,null 代表空位。

示例 1
输入:root = [3,9,20,null,null,15,7]
输出:[[15,7],[9,20],[3]]

解释:最底层 [15,7] 先输出,根 [3] 最后输出。

示例 2
输入:root = [1]
输出:[[1]]

解释:只有一层。

示例 3
输入:root = []
输出:[]

解释:空树返回空列表。

数据范围

  • 节点总数在 [0, 2000] 之间。
  • -1000 <= Node.val <= 1000

解题思路:广度优先搜索 + 反转

先做普通的自顶向下 BFS:每层记下队列长度,弹出这么多个节点组成一层。所有层都收集完后,把层列表整体反转一次即可。只反转层的顺序,不动层内顺序。

为什么正确

每次进入 while 循环时,队列里恰好是下一层的全部节点,按从左到右排列;res 中已有层按自顶向下排列。

复杂度分析

时间 O(n),空间 O(n)。

易错点

只反转层的顺序,不要反转每层内部的顺序。题目要求层与层之间自底向上,层内仍从左到右。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def levelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]:
        res = []
        q = collections.deque([root] if root else [])
        while q:
            level = []
            for _ in range(len(q)):
                node = q.popleft()
                level.append(node.val)
                if node.left:
                    q.append(node.left)
                if node.right:
                    q.append(node.right)
            res.append(level)
        return res[::-1]

载入编辑器,自己跑一遍 →

其他解法

两种方法都先得到自顶向下的层序结果再整体反转;区别只在按层收集节点用队列还是用递归。

解法 2:深度优先搜索 时间 O(n),空间 O(h)

递归时带上深度 depth,第一次到达某个深度时新建一层。按先左后右的顺序递归,把节点值追加到第 depth 层。最后把整个层列表反转。

辅助空间取决于树高 h,不需要队列。深链树递归很深,Python 需要调高递归深度。

import sys

class Solution:
    def levelOrderBottom(self, root):
        sys.setrecursionlimit(10000)
        result = []
        def dfs(node, depth):
            if not node:
                return
            if depth == len(result):
                result.append([])
            result[depth].append(node.val)
            dfs(node.left, depth + 1)
            dfs(node.right, depth + 1)
        dfs(root, 0)
        result.reverse()
        return result

二叉树 专题的其他题目

查看 二叉树 全部题目 →