LC.P654[最大二叉树]

题目描述

给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:

  1. 创建一个根节点,其值为 nums 中的最大值。
  2. 递归地在最大值 左边子数组前缀上 构建左子树。
  3. 递归地在最大值 右边子数组后缀上 构建右子树。

返回 nums 构建的最大二叉树

示例1

输入:nums = [3,2,1,6,0,5]
输出:[6,3,5,null,2,0,null,null,1]
解释:递归调用如下所示:

  • [3,2,1,6,0,5] 中的最大值是 6 ,左边部分是 [3,2,1] ,右边部分是 [0,5] 。
    • [3,2,1] 中的最大值是 3 ,左边部分是 [] ,右边部分是 [2,1] 。
      • 空数组,无子节点。
      • [2,1] 中的最大值是 2 ,左边部分是 [] ,右边部分是 [1] 。
        • 空数组,无子节点。
        • 只有一个元素,所以子节点是一个值为 1 的节点。
    • [0,5] 中的最大值是 5 ,左边部分是 [0] ,右边部分是 [] 。
      • 只有一个元素,所以子节点是一个值为 0 的节点。
      • 空数组,无子节点。

示例2

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

提示:

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000
  • nums 中的所有整数 互不相同

方法一:递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int[] nums;

public TreeNode constructMaximumBinaryTree(int[] nums) {
this.nums = nums;
return build(0, nums.length - 1);
}

private TreeNode build(int left, int right) {
if (left > right) return null;
int maxIndex = left;
for (int i = left; i <= right; ++i) {
if (nums[maxIndex] < nums[i]) maxIndex = i;
}
TreeNode node = new TreeNode(nums[maxIndex]);
node.left = build(left, maxIndex - 1);
node.right = build(maxIndex + 1, right);
return node;
}
}想·
  • 时间复杂度:$O(n²)$
  • 空间复杂度:$O(n)$

方法二:单调栈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
Deque<TreeNode> stack = new ArrayDeque<>();
for (int num : nums) {
TreeNode node = new TreeNode(num);
// 如果当前num值大于栈顶元素,则栈中的元素位num的左子树
while (!stack.isEmpty() && stack.peek().val < num) {
node.left = stack.pop();
}
// 如果栈中还有元素,则说明栈顶元素大于当前元素num,即num为栈顶元素的右子树
if (!stack.isEmpty()) {
stack.peek().right = node;
}
stack.push(node);
}
// 栈底元素即为最大元素
return stack.peekLast();
}
}
  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(n)$

方法三:手写单调栈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
TreeNode[] stack = new TreeNode[nums.length];
int tt = -1;
for (int num : nums) {
TreeNode node = new TreeNode(num);
// 如果当前num值大于栈顶元素,则栈中的元素位num的左子树
while (tt > -1 && stack[tt].val < num) {
node.left = stack[tt--];
}
// 如果栈中还有元素,则说明栈顶元素大于当前元素num,即num为栈顶元素的右子树
if (tt > -1) {
stack[tt].right = node;
}
stack[++tt] = node;
}
// 栈底元素即为最大元素
return stack[0];
}
}
  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(n)$