刷刷刷 Day 20 | 654. 最大二叉树
654. 最大二叉树
LeetCode题目要求
给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:
创建一个根节点,其值为 nums 中的最大值。
递归地在最大值 左边 的 子数组前缀上 构建左子树。
递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回 nums 构建的 最大二叉树 。
示例
输入: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 的节点。
- 空数组,无子节点。
解题思路
需要每次总数组中找到一个最大值,作为分隔点。比如 3,2,1,6,0,5 先找到最大值 6 后,分隔为 3,2,1 子数组和 0,5 两个子数组,然后再在子数组继续找最大值,如此反复。这个过程有些类似于通过后序遍历数组和中序遍历数组构造二叉树的过程。
上代码
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
// 左闭右开
return traversal(nums, 0, nums.length);
}
private TreeNode traversal(int[] nums, int begin, int end) {
if (end - begin < 1) {
return null;
}
if (end - begin == 1) {
return new TreeNode(nums[begin]);
}
// 定义分隔点
int maxPoint = begin;
// 在 nums 中找到最大值
int maxVal = 0;
for (int i = begin; i < end; i++) {
if (nums[i] > maxVal) {
maxVal = nums[i];
maxPoint = i;
}
}
TreeNode root = new TreeNode(maxVal);
// 根据 maxVal 分隔数组
// begin point
// point + 1, end
root.left = traversal(nums, begin, maxPoint);
root.right = traversal(nums, maxPoint + 1, end);
return root;
}
}
重难点
每次找数组中的最大值及对应的下标索引,最大值作为每个子树的root 节点,下标索引用于分隔左右子树,依次递归构造出所有子树
附:学习资料链接