刷题日记19 | 235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

70 阅读2分钟

刷题日记19

今天还是二叉搜索树,二叉搜索树的题型相对还算简单的,要用上二叉搜索树的特点:有序。难点还是递归遍历和逻辑。

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

这道题的逻辑大致和[236]相同,区别是这道题是二叉搜索树,如下是二叉树找公共祖先的算法

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null || root == p || root == q) return root;
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        if(left == null && right == null) return null;
        if(left == null) return right;
        if(right == null) return left;
        return root;
    }
}

二叉搜索树是有序的,那么公共祖先已一定在[p, q]区间或者[q, p]区间内,而在这个区间内的数是不是一定是最近的公共祖先呢?

是!所以我们不需要遍历整个树,找到这个节点就立刻返回,算法如下

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. 二叉搜索树中的插入操作

挺简单的题,不需要重构二叉搜索树,只要见缝插针就好

class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if(root == null) return new TreeNode(val);
        TreeNode cur = root;
        traversal(cur, val);
        return root;
    }
    public void traversal(TreeNode root, int val){
        if(root == null) return;
        if(root.val < val) traversal(root.right, val);
        if(root.val > val) traversal(root.left, val);
        TreeNode node = new TreeNode(val);
        if(root.val < val && root.right == null) root.right = node;
        if(root.val > val && root.left == null) root.left = node;
        return;
    }
}

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

在二叉搜索树中删除节点要比添加节点困难一些,主要是对树结构的修改,依然是遍历二叉搜索树(不用遍历全树),找到了要被删除的节点后,分为4种情况

  1. 找到了 为叶子结点
  2. 找到了 左子树为空
  3. 找到了 右子树为空
  4. 找到了 左右子树都不为空

复杂的是第4种,我们要将这个节点的左子树移植到这个节点的右子树的最左边,使整个树保持二叉搜索树的性质

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if(root == null) return root;
        if(root.val == key){
            // 1. 找到了 为叶子结点
            if(root.left == null && root.right == null){
                return null;
            }
            // 2. 找到了 左子树为空
            else if(root.left == null){
                return root.right;
            }
            // 3. 找到了 右子树为空
            else if(root.right == null){
                return root.left;
            }
            // 4. 找到了 左右子树都不为空
            else{
                TreeNode right = root.right;
                TreeNode left = root.left;
                while(right.left != null){
                    right = right.left;
                }
                right.left = left;
                return root.right;
            }
        }
        if(root.val > key) root.left = deleteNode(root.left, key);
        if(root.val < key) root.right = deleteNode(root.right, key);
        return root;
    }
}