Day20:LeedCode 654.最大二叉树 617.合并二叉树 700.二叉搜索树中的搜索 98.验证二叉搜索树

654. 最大二叉树

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

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

返回 nums 构建的 最大二叉树 

 

示例 1:

 

3c71768d544b08a4c1fc10882b1581c3.jpeg

输入: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 的节点。
        - 空数组,无子节点。

 

思路:采用先序遍历,先找到最大数构造root结点,再根据最大数将数组分为左区间和右区间,分别构造左子树和右子树

图解:

00414dc4916f49c3b17c2783d87865d6.png

递归三部曲:

1.确定返回值和参数类型 

传入需要构造树的数组,返回构造的树

2.确定终止条件

当我们传入的数组只有一个数时,说明该数一定构造叶节点,因为本题1 <= nums.length <= 1000

所以我们不用考虑小于1的情况,那么当递归遍历的时候,如果传入的数组大小为1,说明遍历到了叶子节点了。但是我们分割数组后需要考虑数组长度为0的情况

  if(nums.length==1){
        root.val=nums[0];
        return root;
       }

3.确定单层递归逻辑

找到最大数构造根节点,分割数组为左右区间,构造左右子树

 //找到最大的数作为根节点
       int val=nums[0];
       int index=0;
       for(int i=0;i<nums.length;i++){
            if(val<nums[i]){
                val=nums[i];
                index=i;
            }
        }
        root.val=val;
       //构造左子树
    int[]  left_Tree=Arrays.copyOfRange(nums,0,index);
    int[] right_Tree=Arrays.copyOfRange(nums,index+1,nums.length);
    if(left_Tree.length>0)  root.left=constructMaximumBinaryTree(left_Tree);
    if(right_Tree.length>0)  root.right=constructMaximumBinaryTree(right_Tree);

完整代码参考:

class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
       TreeNode root=  new TreeNode(0);;
       if(nums.length==1){
        root.val=nums[0];
        return root;
       }
       //找到最大的数作为根节点
       int val=nums[0];
       int index=0;
       for(int i=0;i<nums.length;i++){
            if(val<nums[i]){
                val=nums[i];
                index=i;
            }
        }
        root.val=val;
       //构造左子树
    int[]  left_Tree=Arrays.copyOfRange(nums,0,index);
    int[] right_Tree=Arrays.copyOfRange(nums,index+1,nums.length);
    if(left_Tree.length>0)  root.left=constructMaximumBinaryTree(left_Tree);
    if(right_Tree.length>0)  root.right=constructMaximumBinaryTree(right_Tree);
      return root;
    }
}

617. 合并二叉树

给你两棵二叉树: root1 和 root2 。

想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。

返回合并后的二叉树。

注意: 合并过程必须从两个树的根节点开始。

示例 1:

 

66856f28595d62336a7488e90f4366c5.jpeg

输入:root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7]
输出:[3,4,5,5,4,null,7]

思路:本题的关键在于如何同时遍历两个二叉树,其实和遍历一个树逻辑是一样的,只不过传入两个树的节点,同时操作。

递归三要素:

1.确认返回值和参数类型

传入两个数的指针,返回合并后的树的指针

2.确定结束条件

当传入其中一颗树的指针为null时,返回另一个树的指针

3.单层递归逻辑

合并两棵树的当前结点,构造左右子树

root.val=root1.val+root2.val;
root.left=mergeTrees(root1.left,root2.left);
root.right=mergeTrees(root1.right,root2.right);

代码参考:

class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
      if(root1==null)return root2;
      if(root2==null)return root1;
      TreeNode root=new TreeNode(0);
      root.val=root1.val+root2.val;
      root.left=mergeTrees(root1.left,root2.left);
      root.right=mergeTrees(root1.right,root2.right);
      return root;
    }
}

 

700. 二叉搜索树中的搜索

给定二叉搜索树(BST)的根节点 root 和一个整数值 val

你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。

示例 1:

 

cf9e2268f197fce4c0126ecd32e1cd70.jpeg

输入:root = [4,2,7,1,3], val = 2
输出:[2,1,3]

二叉搜索树的特点是:

二叉搜索树是一个有序树:

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 它的左、右子树也分别为二叉搜索树

递归三部曲:

1.确定递归函数的参数和返回值:

递归函数的参数传入的就是根节点和要搜索的数值,返回的就是以这个搜索数值所在的节点。

2.确定终止条件:

当我们遇到空结点说明找不到该数,返回Null

当当前结点的val等于我们要找的数,就返回该节点

 if(root==null) return null;
   if(root.val==val)return root;

3.每层递归逻辑:

如果当前结点数小于目标数,我们search右子树

如果当前结点数大于目标数,我们search左子树

代码参考:

class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
     if(root==null) return null;
     if(root.val==val)return root;
     if(root.val<val) return searchBST(root.right,val);
     if(root.val>val) return searchBST(root.left,val);
     return null;
    }
}

 

98. 验证二叉搜索树

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左

    子树

    只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

 

示例 1:

 

101099972afad76f4747a2a358a6c55d.jpeg

输入:root = [2,1,3]
输出:true

这道题目比较容易陷入两个陷阱:

陷阱1:

不能单纯的比较左节点小于中间节点,右节点大于中间节点就完事了。

我们要比较的是 左子树所有节点小于中间节点,右子树所有节点大于中间节点。

陷阱2

样例中最小节点 可能是int的最小值,如果这样使用最小的int来比较也是不行的。

此时可以初始化比较元素为long的最小值。

思路:我们采用中序遍历,二叉搜索树先序遍历的数一定是递增的,用maxValue记录当前最大值,如果当前结点的值不大于maxValue,则返回false,只有当左右子树都为二叉搜索树并且maxValue<当前结点的val,这棵树才为二叉搜索树

图解:

18004084c7b04187b1ec4efede7fb1e7.png

代码参考:

class Solution {
    long  maxValue=Long.MIN_VALUE;
    public boolean isValidBST(TreeNode root) {
    if(root==null)return true;
     boolean bl=isValidBST(root.left);
     if(maxValue<root.val){
       maxValue=root.val;
     }else return false;
     boolean br= isValidBST(root.right);
     return bl&&br;
    }
}

如果测试数据中有 long的最小值,怎么办?

不可能在初始化一个更小的值了吧。 建议避免 初始化最小值,如下方法取到最左面节点的数值来比较。

用一个结点保存最大值的结点,如果该结点为null,说明之前没有最大值,也就是我们现在遍历到了最左的结点了

 71d51afd804f46eea601d2edbfe17eb4.png

class Solution {
    TreeNode MaxNode=null;
    public boolean isValidBST(TreeNode root) {
    if(root==null)return true;
     boolean bl=isValidBST(root.left);
     if(MaxNode!=null&&MaxNode.val>=root.val){
     return false;
     }else MaxNode=root;
     boolean br= isValidBST(root.right);
     return bl&&br;
    }
}

 

 

 

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-03-26 14:16:05       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-26 14:16:05       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-26 14:16:05       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-26 14:16:05       20 阅读

热门阅读

  1. Git 的基本概念和使用方式

    2024-03-26 14:16:05       18 阅读
  2. 视频中的车流量统计_3.13

    2024-03-26 14:16:05       17 阅读
  3. Unity中使用AssetPostprocessor对模型动画处理

    2024-03-26 14:16:05       21 阅读
  4. Redis 教程系列之Redis 客户端连接(八)

    2024-03-26 14:16:05       15 阅读
  5. Redis 安装

    2024-03-26 14:16:05       19 阅读
  6. 设计模式概念、分类和原则

    2024-03-26 14:16:05       16 阅读
  7. ThreadLocal的主要特点:

    2024-03-26 14:16:05       19 阅读