Leetcode刷题——二叉搜索树相关题目(98. 验证二叉搜索树、235. 二叉搜索树的最近公共祖先、1038. 从二叉搜索树到更大和树、538. 把二叉搜索树转换为累加树)

概念

二叉搜索树:

  • 节点的左子树仅包含键 小于 节点键的节点。
  • 节点的右子树仅包含键 大于 节点键的节点。
  • 左右子树也必须是二叉搜索树。

而二叉搜索树的中序遍历时升序。

98. 验证二叉搜索树

题目:98. 验证二叉搜索树
思路:用中序遍历判断,当前节点是否大于之前一个。

//迭代写法
 public boolean isValidBST(TreeNode root) {
        Stack<TreeNode> stack = new Stack();
        TreeNode cur = root;
        TreeNode pre = null;
        while (cur!=null || !stack.isEmpty()){
            if(cur != null){
                stack.add(cur);
                cur = cur.left;
            }
            else {
                cur = stack.pop();
                if(pre!=null && pre.val>= cur.val){
                    return false;
                }
                //记录前一个节点
                pre=cur;
                cur=cur.right;
            }
        }
        return true;
    }

我一开始用的层次遍历,因为忽略了整体也要大于的情况:
也就是例子中的5、3这种情况。
在这里插入图片描述
当然这里也可以用递归实现,也是中序遍历并记录前一个节点

TreeNode pre=null;
    public boolean isValidBST(TreeNode root) {
       if(root == null ) return true;
        boolean left = isValidBST(root.left);
        //中序遍历操作部分  
        if(pre!=null && root.val <= pre.val){
            return false;
        }
        pre = root;
        boolean right =isValidBST(root.right);
        return left && right;
    }

在这里插入图片描述
我觉得递归还是比较难理解的,虽然思路是一样的但是可能不知道哪一层就出问题了,所以面试遇到还是用迭代不容易出错。

235. 二叉搜索树的最近公共祖先

题目:235. 二叉搜索树的最近公共祖先
这题只需要别人提供一个思路就能写出来:
要求的两个节点都比当前节点小,到左子树中去找
要求的两个节点都比当前节点大,到右子树中去找
如果一个比当前节点大,一个比当前节点小,就是要求的节点。

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    if(p.val<root.val && q.val<root.val){
        return lowestCommonAncestor(root.left, p, q);
    }
    else if(p.val>root.val && q.val>root.val){
        return lowestCommonAncestor(root.right, p, q);
    }
    return root;
}    

在这里插入图片描述

538. 把二叉搜索树转换为累加树

这两道题是一样的
538. 把二叉搜索树转换为累加树
1038. 从二叉搜索树到更大和树

重新建树

第一种思路是容易想到的,先中序遍历得到所有需要的值,然后再次中序遍历给树赋值。

public TreeNode bstToGst(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        inorder(root, list);
        //将list的值设置成题目需要的
        for (int i = list.size() - 2; i >= 0; i--) {
            list.set(i, list.get(i) + list.get(i + 1));
        }
        //重新赋值
        build(root, list);
        return root;
    }

    private static void build(TreeNode root, List<Integer> list) {
        int i = 0;
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while (cur != null || !stack.isEmpty()) {
            if (cur != null) {
                stack.push(cur);
                cur = cur.left;
            } else {
                cur = stack.pop();
                if (cur!=null){
                    cur.val = list.get(i++);
                }
                cur = cur.right;
            }
        }

    }

    private static void inorder(TreeNode root, List<Integer> list) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while (cur != null || !stack.isEmpty()) {
            if (cur != null) {
                stack.push(cur);
                cur = cur.left;
            } else {
                cur = stack.pop();
                //获得中序遍历的值
                list.add(cur.val);
                cur = cur.right;
            }
        }
    }

在这里插入图片描述

递归

将中序遍历反过来就是由大到小,用一个sum记录累加即可。

 int sum = 0;
    public TreeNode bstToGst(TreeNode root) {
        build(root);
        return root;
    }
    //逆中序
    private  void build(TreeNode root){
        if(root!=null){
            build(root.right);
            root.val+=sum;
            sum=root.val;
            build(root.left);
        }
    }

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值