代码随想录-刷题第二十二天

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

题目链接:235. 二叉搜索树的最近公共祖先

思路:根据二叉搜索树的特性,只需要判断当前节点是否在[p,q]范围内就可以,如果在这个范围里,说明当前节点就是其最近公共祖先。

class Solution {
    // 根据二叉搜索树特性,只要当前节点在[p,q]范围内就说明是其最近祖先
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) return null;
        if (p.val > q.val) {
            // 保证 p.val <= q.val,便于后续情况讨论
            return lowestCommonAncestor(root, q, p);
        }
        if (root.val >= p.val && root.val <= q.val) {
            // p <= root <= q
            // 即 p 和 q 分别在 root 的左右子树,那么 root 就是 LCA
            return root;
        }
        if (root.val > q.val) {
            // p 和 q 都在 root 的左子树,那么 LCA 在左子树
            return lowestCommonAncestor(root.left, p, q);
        } else {
            // p 和 q 都在 root 的右子树,那么 LCA 在右子树
            return lowestCommonAncestor(root.right, p, q);
        }
    }
}

精简版:

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

701.二叉搜索树中的插入操作

题目链接:701. 二叉搜索树中的插入操作

思路:如果要递归地插入或者删除二叉树节点,递归函数一定要有返回值,而且返回值需要被正确的接收。

插入的过程可以分两部分:

1、寻找正确的插入位置,类似 700. 二叉搜索树中的搜索

2、把元素插进去,这就要把新节点以返回值的方式接到父节点上。

class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        // 找到空位置插入新节点
        if (root == null) return new TreeNode(val);
        // if (root.val == val)
        //     BST 中一般不会插入已存在元素
        if (root.val < val)
            root.right = insertIntoBST(root.right, val);
        if (root.val > val)
            root.left = insertIntoBST(root.left, val);
        return root;
    }
}

450.删除二叉搜索树中的节点

题目链接:450. 删除二叉搜索树中的节点

思路:删除比插入和搜索都要复杂一些,分三种情况:

情况 1A 恰好是末端节点,两个子节点都为空,那么它可以当场删除;

情况 2A 只有一个非空子节点,那么它要让这个孩子接替自己的位置;

情况 3A 有两个子节点,为了不破坏BST的性质,A 必须找到左子树中最大的那个节点或者右子树中最小的那个节点来接替自己,以下的解法是用右子树中最小节点来替换。

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if (root == null) return null;
        if (root.val == key) {
            // 这两个 if 把情况 1 和 2 都正确处理了
            // 左子树为空,直接返回右子树
            // 右子树为空,直接返回左子树
            // 这里若左右子树均为空,也是返回空
            if (root.left == null) return root.right;
            if (root.right == null) return root.left;
            // 处理情况 3 ,左右子树都不为空
            // 获得右子树最小的节点
            TreeNode minNode = getMin(root.right);
            // 删除右子树最小的节点
            root.right = deleteNode(root.right, minNode.val);
            // 用右子树最小的节点替换 root 节点
            minNode.left = root.left;
            minNode.right = root.right;
            root = minNode;
        } else if (root.val > key) {
            root.left = deleteNode(root.left, key);
        } else if (root.val < key) {
            root.right = deleteNode(root.right, key);
        }
        return root;
    }

    TreeNode getMin(TreeNode node) {
        // BST 最左边的就是最小的
        while (node.left != null) node = node.left;
        return node;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值