LeetCode Java刷题笔记— 450. 删除二叉搜索树中的节点

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

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

中等难度。有两种方式一种是递归,另一种是非递归。

我们首先要找到被值相同的节点A:

  1. 如果该节点的一个子树为空,那么用另一个子树的根节点代替当前节点的位置即可。

  2. 如果该节点的两个子树都为空,那么删除该节点即可,这就是第一种情况的特例。

  3. 如果该节点的左右子树都不为null,那么找到左子树的最大节点或者右子树的最小节点B,此时剩下的步骤有两个思路

    1. 第一种是方法是将A的左子树赋值给B的左子树(如果B是右子树的最小节点),或者将A的右子树赋值给B的右子树(如果B是左子树的最大节点)。
    2. 另一种方法是将找到的节点B的值赋给节点A,然后删除找到的节点B,这样的好处是不会增加树的层级。

迭代算法:

public TreeNode deleteNode(TreeNode root, int key) {

    if (root == null) {
        return null;
    }
    //node 值相等的节点  pre 被删除节点的前驱节点  removeNode 真正被删除的节点
    TreeNode node = root, pre = null, removeNode = root;
    while (node != null) {
        //找到了key相等的节点
        if (node.val == key) {
            //开始查找真正需要删除的节点
            removeNode = node;
            //查找左子树的最大节点
            if (removeNode.left != null && removeNode.right != null) {
                pre = removeNode;
                removeNode = removeNode.left;
                while (removeNode.right != null) {
                    pre = removeNode;
                    removeNode = removeNode.right;
                }
            }
            break;
        }
        pre = node;
        node = node.val > key ? node.left : node.right;
    }
    //如果没找到,那么返回root
    if (node == null) {
        return root;
    }
    //交换值,然后删除真正需要被删除的节点
    node.val = removeNode.val;
    if (pre != null) {
        if (removeNode == pre.left) {
            pre.left = removeNode.left != null ? removeNode.left : removeNode.right;
        }
        if (removeNode == pre.right) {
            pre.right = removeNode.left != null ? removeNode.left : removeNode.right;
        }
        return root;
    }
    root = removeNode.left != null ? removeNode.left : removeNode.right != null ? removeNode.right : null;
    return root;
}

递归算法,更好理解,就是一个dfs递归遍历:

public TreeNode deleteNode(TreeNode root, int key) {
    if (root == null) {
        return null;
    }
    if (root.val > key) {
        root.left = deleteNode(root.left, key);
    } else if (root.val < key) {
        root.right = deleteNode(root.right, key);
    } else {
        //1 2 该节点的至少一个子树为空,返回另一个子树
        if (root.left == null || root.right == null)
            return root.left != null ? root.left : root.right != null ? root.right : null;
        else {
            //3 该节点的左右子树都不为null

            //查找右子树的最小节点p
            TreeNode p = root.right;
            while (p.left != null) {
                p = p.left;
            }
            //root的左子树赋值给p的左子树
            p.left = root.left;
            root = root.right;
            return root;
        }
    }
    return root;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值