在问 · 算法题解

515. 在每个树行中找最大值

中等二叉树广度优先搜索(层序遍历)力扣原题 ↗

题目描述

输入二叉树的根节点 root,树用层序数组表示,空位写 null。

根所在的层记为第 0 层,往下依次是第 1 层、第 2 层……对每一层求出该层所有节点值中的最大值。

按从上到下的层序返回这些最大值组成的数组。空树返回空数组。

示例 1
输入:root = [1,3,2,5,3,null,9]
输出:[1,3,9]

解释:三层的最大值分别是 1、max(3,2) = 3、max(5,3,9) = 9。

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

解释:第 0 层为 1,第 1 层 2 和 3 中取 3。

数据范围

  • 节点个数在 [0, 10^4] 范围内。
  • -2^31 <= Node.val <= 2^31 - 1

解题思路:广度优先搜索(层序遍历)

按层处理就是层序遍历(BFS)。每轮开始时队列里恰好是一整层的节点,先记下 len(q),只弹出这么多个节点,一边弹一边更新本层最大值,并把孩子放到队尾。本层弹完,最大值就确定了,追加到答案。

为什么正确

每轮 while 开始时,队列里恰好是同一层的全部节点,且按从左到右排列。

复杂度分析

时间 O(n),每个节点进出队列各一次;空间 O(w),w 为最宽一层的节点数。

易错点

best 不能初始化为 0(节点值可能全为负数),要用本层第一个节点的值或负无穷;另外必须先固定 len(q) 再循环,否则会把下一层的节点混进本层。

参考代码

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

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

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

其他解法

层序遍历天然按层处理,每层取最大值;深度优先搜索通过记录深度把节点归到对应层,两者都是线性时间。

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

递归遍历时带上当前深度 depth。第一次到达某一层时,结果数组长度正好等于 depth,就把该节点值追加进去;之后再到达这一层的节点,就与已有值比较取最大。

不需要队列,额外空间只与树高有关,代码简短。但“每层”的概念不如层序遍历直观,树退化成链时递归会很深。

class Solution:
    def largestValues(self, root: Optional[TreeNode]) -> List[int]:
        ans = []

        def dfs(node, depth):
            if not node:
                return
            # 第一次到达这一层时追加,之后取最大值
            if depth == len(ans):
                ans.append(node.val)
            else:
                ans[depth] = max(ans[depth], node.val)
            dfs(node.left, depth + 1)
            dfs(node.right, depth + 1)

        dfs(root, 0)
        return ans

二叉树 专题的其他题目

查看 二叉树 全部题目 →