654. 最大二叉树

654. 最大二叉树

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

创建一个根节点,其值为 nums 中的最大值。
递归地在最大值 左边 的 子数组前缀上 构建左子树。
递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回 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]

思考

其实这本身就是一个递归而且题目也描述的较为清楚

首先写个一个函数getMaxIndex(int[] nums,int left,int right) 用来获取nums函数在left到right区间内的最大值的索引。

递归前的初始化:

获取nums函数的最大值的索引,构建根节点

在这里插入图片描述

初始化root的左右子树在数组中的区间rootleft0,rootleft1,rootright0,rootright1,并初始化为-1,其-1代表其根节点不存在左右子树

接下来判断是否存在左右子树
- 如果根节点等于 0 ,根节点不存在左子树
- 如果根节点等于nums.length-1,根节点不存在右子树

如果存在左右子树对其进行赋值

进行递归constructToTree(root,nums,rootleft0,rootleft1,rootright0,rootright1)

首先不需要返回值,因为root是引用变量。

其参数需要节点,数组、其节点的左右子树的范围。

递归结束条件,其不存在左右子树即rootleft0==-1&&rootright0==-1

初始化left=null,right=null

如果根节点存在左子树

- 获取左子树最大值的索引 leftMaxindex 指向的值构建 root.left
- 接下来我们认为leftMaxindex 指向的值作为左子树的根节点 leftTreeRoot
- 我们需要判断根节点leftTreeRoot是否存在左右子树
    - 存在左右子树
        - 进行递归
    - 只存在右子树
        - 进行递归
    - 只存在左子树
        - 进行递归

    注意:其不存在左右子树不用操作了

如果根节点存在右子树

  • 与上类似不在赘述

在这里插入图片描述

    public static TreeNode constructMaximumBinaryTree(int[] nums) {
        int maxIndex = getMaxIndex(nums,0,nums.length-1);
        TreeNode root = new TreeNode(nums[maxIndex]);
        int rootleft0 = -1;
        int rootleft1 = -1;
        int rootright0 = -1;
        int rootright1 = -1;
        if(maxIndex>0){
            rootleft0 = 0;
            rootleft1 = maxIndex-1;
        }
        if(maxIndex<nums.length-1){
            rootright0 = maxIndex+1;
            rootright1 = nums.length-1;
        }

        constructToTree(root,nums,rootleft0,rootleft1,rootright0,rootright1);
        return root;
    }

    private static void constructToTree(TreeNode root, int[] nums, int rootleft0, int rootleft1, int rootright0, int rootright1) {
        if(rootleft0==-1&&rootright0==-1) return;
        TreeNode left = null;
        TreeNode right = null;
        // 存在左子树
        if(rootleft0!=-1){
            int leftMaxIndex = getMaxIndex(nums, rootleft0, rootleft1);
            left = new TreeNode(nums[leftMaxIndex]);
            root.left = left;

            int hasleft = 1;
            int hasright = 1;
            if(leftMaxIndex ==rootleft0) hasleft=0;
            if(leftMaxIndex ==rootleft1) hasright =0;
            // 左子树的最大值作为根节点 有左右子树
            if(hasleft==1&&hasright==1){
                constructToTree(root.left,nums,rootleft0,leftMaxIndex-1,leftMaxIndex+1,rootleft1);
            }
            //  左子树的最大值作为根节点只有左子树
            if(hasleft==1&&hasright==0){
                constructToTree(root.left,nums,rootleft0,leftMaxIndex-1,-1,-1);
            }
            // 只有右子树
            if(hasleft==0&&hasright==1) {
                constructToTree(root.left,nums,-1,-1,leftMaxIndex+1,rootleft1);
            }
            //既没有左子树又没有右子树 不需要操作

        }
        if(rootright0!=-1){
            int rightMaxIndex = getMaxIndex(nums, rootright0, rootright1);
            right = new TreeNode(nums[rightMaxIndex]);
            root.right = right;

            int hasleft = 1;
            int hasright = 1;
            if(rightMaxIndex ==rootright0) hasleft=0;
            if(rightMaxIndex ==rootright1) hasright =0;
            // 有左右子树
            if(hasleft==1&&hasright==1){
                constructToTree(root.right,nums,rootright0,rightMaxIndex-1,rightMaxIndex+1,rootright1);
            }
            // 只有左子树
            if(hasleft==1&&hasright==0){
                constructToTree(root.right,nums,rootright0,rightMaxIndex-1,-1,-1);
            }
            // 只有右子树
            if(hasleft==0&&hasright==1) {
                constructToTree(root.right,nums,-1,-1,rightMaxIndex+1,rootright1);
            }
            //既没有左子树又没有右子树 不需要操作
        }

                                                                                                                                          
    }

    public static int getMaxIndex(int[] nums,int left,int right){
        int max = nums[left];
        int index = left;
        for (int i = left; i<=right;i++){
            if(nums[i]>max) {
                max = nums[i];
                index = i;
            }
        }
        return index;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值