LeetCode 654. 最大二叉树
给定一个不重复的整数数组 nums
。 最大二叉树 可以用下面的算法从 nums
递归地构建:
- 创建一个根节点,其值为
nums
中的最大值。 - 递归地在最大值 左边 的 子数组前缀上 构建左子树。
- 递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回 nums
构建的 最大二叉树 。
链接:https://leetcode.cn/problems/maximum-binary-tree
示例:
输入:nums = [3,2,1,6,0,5]
输出:
这样子形式的树其实就是 笛卡尔树
笛卡尔树有如下性质:
- 中序遍历可以得到原来的数组
- 每个节点的左右子树是在自己区间内距离自己最近的左右最大值
Solution
递归
模拟递归做法,每次在左右区间找到找到最大值以及其索引,并入二叉树。
时间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度:
O
(
1
)
O(1)
O(1)
class Solution:
def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
def dfs(nums: List[int], i: int, j: int) -> Optional[TreeNode]:
if not nums[i:j]:
return None
v = max(nums[i:j])
idx = nums.index(v)
return TreeNode(v, dfs(nums, i, idx), dfs(nums, idx + 1, j))
return dfs(nums, 0, len(nums))
单调栈
演示动画
遍历数组:
- 若栈不空,并且栈顶元素小于当前元素,重复弹出栈顶元素,并将栈顶元素变成当前元素的左孩子
- 若栈顶还有元素(该栈顶元素一定比当前元素大),把当前元素变成栈顶元素的右孩子
- 当前元素入栈
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
n
)
O(n)
O(n)
class Solution:
def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
stack = []
for x in nums:
cur = TreeNode(x)
# 栈不空,且 栈顶元素 < 当前元素, 将栈顶元素变成当前元素的左孩子
while stack and stack[-1].val < x:
cur.left = stack.pop()
# 如果栈顶还有元素,说明 栈顶元素 > 当前元素,将当前元素变成栈顶元素的右孩子
if stack:
stack[-1].right = cur
stack.append(cur)
return stack[0]
最后得到的栈底元素即为最后的根节点。
中序遍历该树就是原数组。