代码随想录第二十天|● 654.最大二叉树 ● 617.合并二叉树 ● 700.二叉搜索树中的搜索 ● 98.验证二叉搜索树

● 654.最大二叉树

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

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

返回 nums 构建的 最大二叉树 

思路

根据题目给出的递归算法,根据前序遍历 先找出最大值,创建根节点,然后递归创建根节点的左右子树即可

递归的三步曲:

        确定参数与返回值

        确定递归终止条件

        确定单次递归的逻辑

class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        TreeNode root = make(nums,0,nums.length-1);
        return root;
    }
    public TreeNode make(int [] nums, int begin, int end){
        if(begin > end) return null;

        int max = nums[begin];
        int index = begin;
        for(int i = begin; i <= end; i++){
            if(max < nums[i]){
                max = nums[i];
                index = i;
            }
        }
        TreeNode root = new TreeNode(max);
        root.left = make(nums, begin, index - 1);
        root.right = make(nums, index + 1, end);
        return root;
    }
}

● 617.合并二叉树

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

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

返回合并后的二叉树。

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

思路

依然是迭代的思路,并且依然前序;同时,若某一方为null 直接返回另一个,因为不需要合并了。

注:构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树。

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

● 700.二叉搜索树中的搜索

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

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

思路

递归/迭代,因为是二叉搜索树,所以前序遍历

递归

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

迭代

class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        if(root == null){
            return root;
        }
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode cur = stack.pop();
            if(cur.val == val) return cur;
            else if(cur.val < val){
                if(cur.right != null){
                    stack.push(cur.right);
                }else{
                    return null;
                }
            }else{
                if(cur.left != null){
                    stack.push(cur.left);
                }else{
                    return null;
                }
            }
        }
        return null;
    }

}

● 98.验证二叉搜索树 

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

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

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

思路

递归判断,但要注意,

  • 节点的左子树只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。

因此,在比较root时需要将root的值与左侧最大比、与右侧最小比

要大于左侧最大,小于右侧最小

因此可以采用 递归套递归(利用递归寻找左、右子树的最值)

不过在看完题解后,发现这是一个比较笨的方法了

更快速的方法:

       法 ① 中序遍历树,如果树是一个二叉搜索树,那么中序遍历的结果一定是递增的。

        法② 递归,但修改单次递归的操作,上述方法的单次递归实际在做的是 判断左、右子树是不是二叉搜索树、判断当前子树是不是二叉搜索树。更加简便的思路是 中序遍历,找到最左下角的元素,记录是否递增,是则继续,否则return false

不太好的做法

class Solution {
    public boolean isValidBST(TreeNode root) {
        return judge(root);
    }
    public boolean judge(TreeNode root){
        if(root == null) return true;
        if(root.left == null && root.right == null) return true;
        //此时root非空,left/right至少有一个非空
        int val = root.val;
        boolean b1 = true,b2 = true;
        if(root.left != null){
            if(val <= getmax(root.left)) return false;
            b1 = judge(root.left);
        }
        if(root.right != null){
            if(val >= getmin(root.right)) return false;
            b2 = judge(root.right);
        }
        return b1 && b2;
    }
    public int getmax(TreeNode root){
        if(root == null) return -1;
        int max = root.val;
        Queue<TreeNode> que = new LinkedList<TreeNode>();
        que.offer(root);
        while(!que.isEmpty()){
            int len = que.size();
            for(int i = 0; i<len; i++){
                TreeNode cur = que.poll();
                if(cur.val > max){
                    max = cur.val;
                }
                if(cur.left != null) que.offer(cur.left);
                if(cur.right != null) que.offer(cur.right);
            }
        }
        return max;
    }
    public int getmin(TreeNode root){
        if(root == null) return -1;
        int max = root.val;
        Queue<TreeNode> que = new LinkedList<TreeNode>();
        que.offer(root);
        while(!que.isEmpty()){
            int len = que.size();
            for(int i = 0; i<len; i++){
                TreeNode cur = que.poll();
                if(cur.val < max){
                    max = cur.val;
                }
                if(cur.left != null) que.offer(cur.left);
                if(cur.right != null) que.offer(cur.right);
            }
        }
        return max;
    }
}

法①判断是否递增

class Solution {
private:
    vector<int> vec;
    void traversal(TreeNode* root) {
        if (root == NULL) return;
        traversal(root->left);
        vec.push_back(root->val); // 将二叉搜索树转换为有序数组
        traversal(root->right);
    }
public:
    bool isValidBST(TreeNode* root) {
        vec.clear(); // 不加这句在leetcode上也可以过,但最好加上
        traversal(root);
        for (int i = 1; i < vec.size(); i++) {
            // 注意要小于等于,搜索树里不能有相同元素
            if (vec[i] <= vec[i - 1]) return false;
        }
        return true;
    }
};

法②递归

class Solution {
    // 递归
    TreeNode max;
    public boolean isValidBST(TreeNode root) {
        if (root == null) {
            return true;
        }
        // 左
        boolean left = isValidBST(root.left);
        if (!left) {
            return false;
        }
        // 中
        if (max != null && root.val <= max.val) {
            return false;
        }
        max = root;//记录前一个节点
        // 右
        boolean right = isValidBST(root.right);
        return right;
    }

迭代

迭代模拟中序遍历即可

class Solution {
    // 迭代
    public boolean isValidBST(TreeNode root) {
        if (root == null) {
            return true;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode pre = null;
        while (root != null || !stack.isEmpty()) {
            while (root != null) {
                stack.push(root);
                root = root.left;// 左
            }
            // 中,处理
            TreeNode pop = stack.pop();
            if (pre != null && pop.val <= pre.val) {
                return false;
            }
            pre = pop;

            root = pop.right;// 右
        }
        return true;
    }
}

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值