Bootstrap

day16最大二叉树&合并二叉树&二叉搜索树中搜索&验证二叉搜索树(递归详解版)

        今天主要学习了二叉搜索树的相关题目,学习到怎么同时递归操作两棵树。

1.力扣654(最大二叉树)

        首先我们要知道最大二叉树是什么,下面是最大二叉树的定义

  • 二叉树的根是数组中的最大元素。
  • 左子树是通过数组中最大值左边部分构造出的最大二叉树。
  • 右子树是通过数组中最大值右边部分构造出的最大二叉树。

                       

        本题方便理解,我们利用前序遍历来构建二叉树,我们首先创建中节点,然后创建左节点和右节点,接下来用递归三部曲来创建:

  • 确定递归函数的参数和返回值:参数就是传入的是存放元素的数组和左右边界,返回该数组构造的二叉树的头结点。
    public TreeNode constructTree(int[] nums,int leftIndex,int rightIndex) 
  • 确定终止条件:当区间元素就剩一个的时候,我们直接返回并创建节点,若左右边界混乱时,我们也返回
        if (rightIndex - leftIndex < 1) {// 没有元素了
            return null;
        }
        if(rightIndex-leftIndex==1){
            return new TreeNode(nums[leftIndex]);
        }
  • 确定单层递归的逻辑:首先我们先遍历出数组中的最大值,然后我们进行创建节点,随后我们创建中节点,然后我们递归创建左区间和右区间
        //中
        int maxValue = nums[leftIndex];
        int maxIndex = leftIndex;
        for(int i=leftIndex;i<rightIndex;i++){
            if(nums[i]>maxValue){
                maxValue=nums[i];
                maxIndex = i;
            }
        }
        TreeNode node = new TreeNode(maxValue);
        //左
        node.left = constructTree(nums,leftIndex,maxIndex);
        //右
        node.right = constructTree(nums,maxIndex+1,rightIndex);
        return node;

下面是整体代码

    public TreeNode constructMaximumBinaryTree(int[] nums) {
        if(nums.length==1){
            return new TreeNode(nums[0]);
        }
        return constructTree(nums,0,nums.length);
    }

    public TreeNode constructTree(int[] nums,int leftIndex,int rightIndex) {
        if (rightIndex - leftIndex < 1) {// 没有元素了
            return null;
        }
        if(rightIndex-leftIndex==1){
            return new TreeNode(nums[leftIndex]);
        }
        //中
        int maxValue = nums[leftIndex];
        int maxIndex = leftIndex;
        for(int i=leftIndex;i<rightIndex;i++){
            if(nums[i]>maxValue){
                maxValue=nums[i];
                maxIndex = i;
            }
        }
        TreeNode node = new TreeNode(maxValue);
        //左
        node.left = constructTree(nums,leftIndex,maxIndex);
        //右
        node.right = constructTree(nums,maxIndex+1,rightIndex);
        return node;
    }

2.力扣617(合并二叉树)

                        

        合并二叉树这个题目的重点是递归操作两个二叉树,若相同位置处的某个节点为空就直接返回不为空的那个节点,若都存在的话就相加后并返回,最终返回根节点。下面利用递归三部曲来构建二叉树:

  • 确定递归函数的参数和返回值:首先那么要合入两个二叉树,那么参数至少是要传入两个二叉树的根节点,返回值就是合并之后二叉树的根节点。
    public TreeNode mergeTree(TreeNode root1, TreeNode root2)
  • 确定终止条件:因为是传入了两个树,那么就有两个树遍历的节点,此时会有三种情况发生:若其中一个为空,就返回另一个,若都不为空就相加后返回。
        if(root1==null){
            return root2;
        }
        if(root2==null){
            return root1;
        }
  • 确定单层递归的逻辑:这里我们直接进行相加操作就可以了
        root1.val+=root2.val;
        root1.left= mergeTree(root1.left,root2.left);
        root1.right=mergeTree(root1.right,root2.right);
        return root1;

整体代码如下:

    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        return mergeTree(root1,root2);
    }

    public TreeNode mergeTree(TreeNode root1, TreeNode root2) {
        if(root1==null){
            return root2;
        }
        if(root2==null){
            return root1;
        }
        root1.val+=root2.val;
        root1.left= mergeTree(root1.left,root2.left);
        root1.right=mergeTree(root1.right,root2.right);
        return root1;
    }

3.力扣700(二叉搜索树中搜索)

                                

        在本题中我们要充分利用二叉搜索树中的这个结构,即节点的左子树都小于中节点,右节点都大于中节点,本体利用递归三部曲来解决:

  • 确定递归函数的参数和返回值:递归函数的参数传入的就是根节点和要搜索的数值,返回的就是以这个搜索数值所在的节点。
    public TreeNode search(TreeNode root, int val) 
  • 确定终止条件:如果root为空,或者找到这个数值了,就返回root节点。
        if(root==null||root.val==val){
            return root;
        }
  • 确定单层递归的逻辑:若节点值大于目标值就去左子树找,否则就去右子树找
        TreeNode res = null;
        if(val<root.val){
            res = search(root.left,val);
        }
        if(val>root.val){
            res = search(root.right,val);
        }
        return res;

整体代码:

    public TreeNode searchBST(TreeNode root, int val) {
        return search(root,val);
    }

    public TreeNode search(TreeNode root, int val) {
        if(root==null||root.val==val){
            return root;
        }
        TreeNode res = null;
        if(val<root.val){
            res = search(root.left,val);
        }
        if(val>root.val){
            res = search(root.right,val);
        }
        return res;
    }

4.力扣98(验证二叉树)

                                

        本题要来验证二叉搜索树,容易犯的错误就是只比较中节点大于左右孩子节点,我们应该比较的是中节点和整个左子树的大小和右子树的大小,其次解决本题最重要的一点就是二叉搜索树在中序遍历的时候,会保持单调递增的顺序,所以我们可以定义一个节点指向前一个结点,以此向下遍历。下面利用递归三部曲来解决:

  • 确定递归函数返回值以及参数:我们在定义了一个全局节点,用来记录上一个接单。
    public boolean isBST(TreeNode root)
  • 确定终止条件:若节点为空就返回
        if(root==null){
            return true;
        }
  • 确定单层递归的逻辑:首先判断左节点,然后判断前一个结点是否满足小于后一个节点,若不满足就返回false,然后递归判断右节点。
        //左
        boolean left = isBST(root.left);

        if(pre!=null&&pre.val>=root.val){
            return false;
        }
        pre =root;

        //右
        boolean right = isBST(root.right);
        return left&right;

整体代码:

    TreeNode pre = null;
    public boolean isValidBST(TreeNode root) {
        return isBST(root);
    }
    public boolean isBST(TreeNode root) {
        if(root==null){
            return true;
        }
        //左
        boolean left = isBST(root.left);

        if(pre!=null&&pre.val>=root.val){
            return false;
        }
        pre =root;

        //右
        boolean right = isBST(root.right);
        return left&right;
    }
;