Skip to content

Day 17


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

相对于 二叉树的最近公共祖先 本题就简单一些了,因为 可以利用二叉搜索树的特性。

题目链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/description/

文章讲解:https://programmercarl.com/0235.二叉搜索树的最近公共祖先.html

视频讲解:https://www.bilibili.com/video/BV1Zt4y1F7ww

思路分析

利用二叉搜索树的特性,左子树的值都是比根节点小的,右子树都是比根节点大的,利用这个特性来搜索 p、q 的值

此时还需要考虑是否是最近公共祖先,如下图

如果向左遍历错失 q,向右遍历错失了 p,整理后可以得到以下思路

  • 首先向左右搜索遍历,依据二叉搜索树节点值的大小关系,找到符合条件的节点返回
  • 然后剩余的情况就是中间节点的情况,直接返回即可

题解

java
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        // p,q 在左子树
        if (root.val > p.val && root.val > q.val) {
            return lowestCommonAncestor(root.left, p, q);
        }
        // p,q 在右子树
        if (root.val < p.val && root.val < q.val) {
            return lowestCommonAncestor(root.right, p, q);
        }
        return root;
    }
}

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

题目链接:https://leetcode.cn/problems/insert-into-a-binary-search-tree/

文章讲解:https://programmercarl.com/0701.二叉搜索树中的插入操作.html

视频讲解:https://www.bilibili.com/video/BV1Et4y1c78Y

思路分析

审题可以发现,虽然插入结果可以有多种,但是目的是只要成功插入节点即可,即在叶子节点中插入节点,利用二叉搜索树的节点值大小关系递归查找叶子节点,插入节点即可

题解

java
class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        // 在叶子节点插入节点
        if (root == null) {
            TreeNode node = new TreeNode(val);
            return node; // 返回给父节点
        }

        // 利用二叉搜索树的特性
        if (root.val < val){
            root.right = insertIntoBST(root.right, val); // 递归创建右子树
        }else if (root.val > val){
            root.left = insertIntoBST(root.left, val); // 递归创建左子树
        }
        return root;
    }
}

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

相对于 插入操作,本题就有难度了,涉及到改树的结构

题目链接:https://leetcode.cn/problems/delete-node-in-a-bst/

文章讲解:https://programmercarl.com/0450.删除二叉搜索树中的节点.html

视频讲解:https://www.bilibili.com/video/BV1tP41177us

思路分析

  • 第一种情况:没找到删除的节点,遍历到空节点直接返回了
  • 找到删除的节点
    • 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回 NULL 为根节点
    • 第三种情况:删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点
    • 第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
    • 第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。

题解

java
class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        // 没有找到删除节点
        if (root == null) {
            return root;
        }
        // 找到了删除节点,分以下五种情况
        if (root.val == key) {
            // 叶子节点
            if (root.left == null && root.right == null) {
                return null;
            }
            // 左子树为空
            else if (root.left == null) {
                return root.right;
            }
            // 右子树为空
            else if (root.right == null) {
                return root.left;
            }
            // 左右子树不为空
            TreeNode cur = root.right; // 指向被删节点右子树的根节点
            while (cur.left != null) {
                cur = cur.left; // 找到被删节点右子树的根节点的左孩子
            }
            cur.left = root.left; // 重新链接被删节点的左子树
            root = root.right; // 改变指向,删除节点
            return root;
        }
        // 在递归中调用,实现删除的逻辑
        if (root.val > key) {
            root.left = deleteNode(root.left, key);
        }
        if (root.val < key) {
            root.right = deleteNode(root.right, key);
        }

        return root;
    }
}