力扣-最大二叉树

135 阅读3分钟

「这是我参与2022首次更文挑战的第30天,活动详情查看:2022首次更文挑战」。

最大二叉树

题目描述

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

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

image.png

输入: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:

image.png

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

算法解析

这道题实质上就是构造二叉树,可以分为三部分,根节点,左子树,右子树.
中心思想就是找出数组中的最大值作为根节点,然后利用根节点左边的节点去构造左子树,利用根节点右边的节点去构造右子树,这里采用的是前序遍历,因为前序遍历的顺序就是先构造根节点,然后递归构造左子树和右子树.

算法的详细步骤为:

首先构造双指针leftIndex和rightIndex分别指向数组的首元素和末尾元素

  • 判断是否为空的二叉树,若为空则返回空
  • 判断是否为只有一个节点的二叉树,若只有一个则作为根节点
    排除以上两种情况外做以下操作:
  1. 找出数组中最大值以及最大值对应的数组下标,作为二叉树的根节点
  2. 确定根节点的位置之后,选中左区间的数组元素构造左子树,递归构造左子树.
  3. 确定根节点的位置之后,选中右区间的数组元素构造右子树,递归构造右子树.

代码描述

public TreeNode constructMaximumBinaryTree(int[] nums) {
        //数组nums构造二叉树
        return construct(nums,0,nums.length);
    }
    public TreeNode construct(int[] nums,int leftIndex,int rightIndex){
        //此时表示没有元素,返回空
        if(rightIndex==leftIndex){
            return null;
        }
        //此时表示只有一个数组元素,该数组元素作为根节点
        if(rightIndex-leftIndex<1){
            return new TreeNode(nums[leftIndex]);
        }
        //依次遍历找出数组中的最大值
        int maxIndex=leftIndex;
        int maxVal=nums[maxIndex];
        for(int i=leftIndex+1;i<rightIndex;i++){
            if(nums[i]>maxVal){
                maxVal=nums[i];
                maxIndex=i;
            }
        }
        //最大值作为根节点
        TreeNode root=new TreeNode(maxVal);
        //递归构造左子树
        root.left=construct(nums,leftIndex,maxIndex);
        //递归构造右子树
        root.right=construct(nums,maxIndex+1,rightIndex);
        return root;
    }