代码随想录第17天|二叉搜索树中的搜索,验证二叉搜索树,合并二叉搜索树,最大二叉树

文章讲述了如何构建最大二叉树、合并两个二叉树、利用二叉搜索树特性进行搜索及验证的方法,包括递归和迭代解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章:代码随想录

最大二叉树:

思路:

这道题其实就是day16中后序构建二叉树的简易版,有了昨天的思路这题很容易做.

代码:

  public TreeNode constructMaximumBinaryTree(int[] nums) {
        if(nums.length==0){return null;}

        //左闭右开
        return getTree(nums,0,nums.length);
    }

    private TreeNode getTree(int[] nums, int start, int end) {
        if(start==end) return null;
        int maxIndex=0;
        int max=-1;
        for (int i = start; i <end ; i++) {
            if(nums[i]>max){max=nums[i]; maxIndex=i;}
        }
        TreeNode node=new TreeNode(max);
        //定义左子树区间范围
        int leftStart=start;
        int leftEnd=maxIndex;
        //定义右子树区间范围
        int rightStart=maxIndex+1;
        int rightEnd=end;

        node.left=getTree(nums,leftStart,leftEnd);
        node.right=getTree(nums,rightStart,rightEnd);

        return node;
    }

合并二叉树:

思路:

其实就是同时遍历两棵二叉树,将两个都不为空的节点值相加生成一颗新的节点,如果有一颗相同节点位置的树节点为空,另一棵不为空,那么就直接返回/指向另一颗不为空的树节点就行,因为空和不为空的节点值相加,其实就是不为空的节点本身.

代码:

//前序遍历
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if(root1==null && root2==null){return null;}
        //因为没有说一点是相同深度的二叉树相合并,那么就说明可能存在有第一棵树左边还有,但是右边的树左边没有了.
        //这里的逻辑是当这种情况发生时,其实直接返回有的那一边子树就可以了.因为如果另一颗树没有了,接下来的所有数值的和其实也就是这颗树的本身.
        if(root1==null){return root2;}
        if(root2==null){return root1;}

        //创建一个新节点
        TreeNode node=new TreeNode();
        node.val=root1.val+root2.val;

        node.left=mergeTrees(root1.left,root2.left);
        node.right=mergeTrees(root1.right,root2.right);

        return node;
    }
    //用栈迭代法,用队列也行(都是两两抛出比较) 前序遍历
    //这里思路是直接改变root1的结构,最后返回root1.
    public TreeNode mergeTreesLevel(TreeNode root1, TreeNode root2) {
        if (root1 == null) {
            return root2;
        }
        if (root2 == null) {
            return root1;
        }
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root2);
        stack.push(root1);
        while (!stack.isEmpty()) {
            TreeNode node1 = stack.pop();
            TreeNode node2 = stack.pop();
            node1.val += node2.val;
            //因为用栈模拟,所以先右后左
            //判断右子树情况
            if (node2.right != null && node1.right != null) {
                stack.push(node2.right);
                stack.push(node1.right);
            } else {
                if (node1.right == null) {
                    node1.right = node2.right;
                }
            }
            //判断左子树情况
            if (node2.left != null && node1.left != null) {
                stack.push(node2.left);
                stack.push(node1.left);
            } else {
                if (node1.left == null) {
                    node1.left = node2.left;
                }
            }
        }
        return root1;
    }

二叉搜索树中的搜索树:

这里主要是要明白搜索树的特性以及利用,利用二叉树特性可以写出更简洁的代码.

二叉搜索树特性:

左子树所有节点的元素值均小于根的元素值;右子树所有节点的元素值均大于根的元素值。

我原本不知道二叉树的特性时写的代码如下:

 //自写初代版,没利用特性
    public TreeNode searchBST(TreeNode root, int val) {

        if(root==null)return null;
        if(root.val==val){return root;}
        TreeNode left=searchBST(root.left,val);
        TreeNode right=searchBST(root.right,val);

        if(left!=null) return left;
        if(right !=null) return right;

        return null;

    }

后面可以根据特性写出递归和迭代法:

因为它本来就是二叉搜索树了,所以如果当前节点比目标值小,则往大的方向找,也就是往右子树找,反之则往左子树找.

 //利用特性 递归版
    //若 root 为空则返回空节点;
    //若 val=root.val,则返回 root;
    //若 val<root.val.递归左子树;
    //若 val>root.val,递归右子树

    public TreeNode searchBSTR1(TreeNode root, int val) {
        if(root==null)return null;
        if(root.val==val) return root;

        return root.val<val?searchBST(root.right,val):searchBST(root.left,val);
    }

    //迭代法,利用二叉树特性
    public TreeNode searchBSTT2(TreeNode root, int val) {
        if(root==null) return null;
        while(root!=null){
            if(root.val==val) return root;
            root=val>root.val?root.right:root.left;
        }
        return null;
    }

验证二叉搜索树:

思路:

其实也是要利用二叉搜索树的特性:

中序遍历这颗树的话,得到的结果是有序的。

直白想法:

将中序遍历的结果存在数组中,最后判断这个数组是不是无重复升序的. 但是这样性能很差,不是最优解。

代码:

 ArrayList<Integer> result=new ArrayList<>();
    void inTraversal(TreeNode root){
        if(root==null) return;
        inTraversal(root.left);
        result.add(root.val);
        inTraversal(root.right);
    }
    public boolean isValidBST(TreeNode root) {
        inTraversal(root);
        Boolean flag=true;
        for(int i=1;i<result.size();i++){
            if(result.get(i)<=result.get(i-1)) flag=false;
        }

        return flag;
    }

双指针优化:

做一个优化,在递归迭代的过程中就可以去比较是不是单调递增的,因为中序遍历的过程种就可以比较. 做一个双指针优化,用一个指针指向上一个节点,这样中序遍历的过程中就可以比较;

注意得是中序遍历

代码:

 TreeNode pre=null;
    public boolean isValidBSTDouble(TreeNode root) {
        if(root==null){return true;}
        Boolean left=isValidBSTDouble(root.left);
        //前一个必须小于目前的节点
        if(pre!=null && pre.val>=root.val)return false;
        pre=root;
        Boolean right=isValidBSTDouble(root.right);

        return left && right;

    }

迭代版本:

 //迭代法:
    public boolean isValidBSTStack(TreeNode root) {
        if(root == null) return  true;
        Stack<TreeNode> stack = new Stack<>();
        TreeNode pre = null;
        stack.add(root);
        while(!stack.isEmpty()){
            TreeNode curr = stack.pop();
            if(curr != null){
                if(curr.right != null)
                    stack.add(curr.right);
                stack.add(curr);
                stack.add(null);
                if(curr.left != null)
                    stack.add(curr.left);
            }else{
                //cur等于null的时候开始弹出
                TreeNode temp = stack.pop();
                //pre值必须更小,pre如果更大则不是升序
                if(pre != null && pre.val >= temp.val)
                    return false;
                pre = temp;
            }
        }
        return true;
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值