代码随想录算法训练营day20 | 654.最大二叉树 617.合并二叉树 700.二叉搜索树中的搜索 98.验证二叉搜索树

86 阅读5分钟

654.最大二叉树

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

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

654. 最大二叉树 - 力扣(Leetcode)

思路

  • 给定数组的左右边界,分别是leftIndexrightIndex;
  • 如果leftIndex > rightIndex,则这个数组已经没有元素了,返回null;
  • 否则,遍历数组,找到数组当前最大值在数组中的下标maxIndex;
  • 通过 maxIndex 将数组划分成左右子树;边界为:
    • 左子树: [leftIndex, maxIndex - 1];
    • 右子树: [maxIndex + 1, rightIndex];
  • 创建节点node,其值为nums[maxIndex];
  • node的左孩子由左子树的数组递归得到;
  • node的右孩子由右子树的数组递归得到;
  • 返回node节点。

代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        return buildSubTree(0, nums.length - 1, nums);
    }

    private TreeNode buildSubTree(int leftIndex, int rightIndex, int[] nums){
        if(leftIndex > rightIndex){
            return null;
        }

        int maxIndex = leftIndex;
        for(int i= leftIndex + 1;i<=rightIndex;i++){
            if(nums[i]> nums[maxIndex]){
                maxIndex = i;
            }
        }

        // 通过 maxIndex 将数组划分成左右子树
        // 左子树: [leftIndex, maxIndex - 1]
        // 右子树: [maxIndex + 1, rightIndex]

        TreeNode node = new TreeNode(nums[maxIndex]);
        node.left = buildSubTree(leftIndex, maxIndex -1, nums);
        node.right = buildSubTree(maxIndex + 1, rightIndex, nums);

        return node;
    }
}

617.合并二叉树

给你两棵二叉树: root1 和 root2 。
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。
合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
返回合并后的二叉树。
注意:  合并过程必须从两个树的根节点开始。

617. 合并二叉树 - 力扣(Leetcode)

思路

要合并root1 和 root2,我们随意地选择在root1上进行合并(root2也可以,此处以root1为例)。

参数: root1的节点node1,root2的节点node2;

在合并一棵子树时,

  • 如果node1node2都是null,没有要合并的节点,返回null;
  • 否则,若两个节点有一个为null,则要合并的节点为不为null的节点,将其返回;
  • 排除以上两种情况后,两个节点都不为null,需要对此节点进行合并;将node1的值修改成node1.val + node2.val;
  • 继续递归,
  • node1的左孩子由node1node2的左孩子合并而成;
  • node1的右孩子由node1node2的右孩子合并而成;
  • 返回node1

代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        return mergeSubTrees(root1,root2);
    }

    private TreeNode mergeSubTrees(TreeNode node1, TreeNode node2){

        if(node1 == null && node2 == null){
            return null;
        }

        if(node1 == null && node2 !=null){
            return node2;
        }

        if(node1 != null && node2 ==null){
            return node1;
        }

        node1.val = node1.val + node2.val;

        // 左
        node1.left = mergeSubTrees(node1.left,node2.left);

        // 右
        node1.right = mergeSubTrees(node1.right,node2.right);

        return node1;
    }
}

700.二叉搜索树中的搜索

给定二叉搜索树(BST)的根节点 root 和一个整数值 val
你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。

700. 二叉搜索树中的搜索 - 力扣(Leetcode)

思路

使用前序遍历的遍历方法,

  • 如果当前节点为null,即当前遍历路径上没有找到满足条件的节点,返回null;
  • 否则,判断当前节点的值等于目标值,即当前节点就是要找的节点,将其返回;
  • 否则,当前节点不满足条件,分别在当前节点的左右子树中寻找满足条件的节点,并将搜索结果返回。

代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode searchBST(TreeNode root, int val) {

        if(root == null){
            return null;
        }

        if(root.val == val){
            return root;
        }

        TreeNode leftRes = searchBST(root.left,val);

        TreeNode rightRes =searchBST(root.right,val);

        return leftRes == null ? rightRes : leftRes;
    }
}

98.验证二叉搜索树

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

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

98. 验证二叉搜索树 - 力扣(Leetcode)

思路

二叉搜索树的特性是中序遍历二叉树时,元素从小到大排列

  • 初始化一个当前最大值maxValue,为Long类型的最小值。
  • 对于当前节点,
    • 递归遍历当前节点的左子树,判断当前节点的左子树是否为二叉搜索树,结果为leftValid;
    • 如果当前节点的值小于或等于maxValue,这意味着存在当前节点前面工节点中存在大于当前节点的节点,不符合二叉搜索树的特性,返回false
    • 否则,用当前节点的值更新maxValue
    • 递归遍历当前节点的右子树,判断当前节点的右子树是否为二叉搜索树,结果为rightValid;
    • 返回 leftValid && rightValid,只有二者同时为true·,返回值才为true`,此时意味着当前节点及其左右子树都满足二叉搜索树的特性。

代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {

    private long maxValue = Long.MIN_VALUE;

    public boolean isValidBST(TreeNode root) {

        if(root == null){
            return true;
        }

        // 左
        boolean leftValid = isValidBST(root.left);

        // 中
        if(maxValue >= root.val){
            return false;
        }

        // 更新 maxValue
        maxValue = root.val;

        // 右
        boolean rightValid = isValidBST(root.right);

        return leftValid && rightValid;

        
    }

}