在问 · 算法题解

654. 最大二叉树

中等二叉树递归分治力扣原题 ↗

题目描述

输入一个各元素互不相同的整数数组 nums,按下面的规则递归地建一棵二叉树。

取当前数组中的最大值作为根。最大值左侧的那段元素用同样的方法建成左子树,右侧的那段元素建成右子树。某一侧没有元素时,对应的子树为空。

返回建好的树的根节点,输出用层序数组表示,null 表示空位。

示例 1
输入:nums = [3,2,1,6,0,5]
输出:[6,3,5,null,2,0,null,null,1]

解释:6 为根;左侧 [3,2,1] 以 3 为根,并沿右侧依次挂上 2 和 1;右侧 [0,5] 以 5 为根,0 是它的左孩子。

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

解释:数组递减,每个节点都只有右孩子。

数据范围

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000
  • nums 中的元素互不相同。

解题思路:递归分治

直接按定义递归:build(lo, hi) 负责区间 nums[lo..hi]。区间为空返回 None;否则扫一遍找到最大值下标 m,用 nums[m] 建节点,左子树 = build(lo, m-1),右子树 = build(m+1, hi)。只传下标不切片,避免复制数组。

为什么正确

build(lo, hi) 返回的树恰好包含 nums[lo..hi] 的全部元素,其中序遍历就是这段区间本身。

复杂度分析

时间平均 O(n log n),最坏 O(n²)(数组有序时树退化成链);用单调栈可以做到 O(n)。空间 O(n) 递归栈。

易错点

左右子区间要排除 m 自己:左是 [lo, m-1],右是 [m+1, hi];写成 [lo, m] 会无限递归。空区间的判断是 lo > hi,不是 lo >= hi(否则丢掉单元素区间)。

参考代码

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

class Solution:
    def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
        def build(lo, hi):
            if lo > hi:
                return None
            m = lo
            for i in range(lo + 1, hi + 1):
                if nums[i] > nums[m]:
                    m = i
            node = TreeNode(nums[m])
            node.left = build(lo, m - 1)
            node.right = build(m + 1, hi)
            return node
        return build(0, len(nums) - 1)

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

其他解法

递归分治直接照定义找最大值,数组有序时退化到 O(n²);单调栈用“左右两侧第一个更大的数”确定父节点,一次扫描建好整棵树。

解法 2:单调栈 时间 O(n),空间 O(n)

从左到右扫描,维护一个节点值从底到顶递减的栈。对新节点,把栈顶比它小的节点依次弹出,最后弹出的那个就是它的左孩子。弹完后栈非空,就把新节点设为栈顶的右孩子。再把新节点入栈。扫描结束后栈底就是根。

每个节点只入栈出栈一次,线性时间。代价是要想清楚“左侧第一个更大的数”与父子关系的对应,不如递归直观。

class Solution:
    def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
        stk = []
        for v in nums:
            node = TreeNode(v)
            last = None
            while stk and stk[-1].val < v:
                last = stk.pop()
            node.left = last
            if stk:
                stk[-1].right = node
            stk.append(node)
        return stk[0]

二叉树 专题的其他题目

查看 二叉树 全部题目 →