LeetCode 每日一题——450. 删除二叉搜索树中的节点

1.题目描述

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

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

一般来说,删除节点可分为两个步骤:

首先找到需要删除的节点;
如果找到了,删除它。

示例 1:

输入:root = [5,3,6,2,4,null,7], key = 3
输出:[5,4,6,2,null,null,7]
解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
另一个正确答案是 [5,2,6,null,4,null,7]。

示例 2:

输入: root = [5,3,6,2,4,null,7], key = 0
输出: [5,3,6,2,4,null,7]
解释: 二叉树不包含值为 0 的节点

示例 3:

输入: root = [], key = 0
输出: []

2.解题思路与代码

2.1 解题思路

题目要求在二叉搜索树中删除节点,并让删除后的二叉树仍然是二叉搜索树,那么就需要查找节点和删除节点两个步骤。

查找节点
由于是二叉搜索树,查找节点比较简单,可以选择使用迭代也可以选择使用递归的方式进行查找。这里是用递归进行解答,因为使用迭代的话需要维护查找节点的前一节点,并且需要判断查找到的节点是根结点、是前一节点左树还是右树等等,代码较为复杂,因此选用递归解答。在查找时根据二叉搜索树的性质,如果节点值大于要查找的值,则往左子树查找;如果节点值小于要查找的值,则往右子树查找。

删除节点
在查找到节点之后,便需要对该节点进行删除,删除有以下四种情况:

  • 当前节点既没有左子树,也没有右子树
  • 当前节点只有左子树,没有右子树
  • 当前节点只有右子树,没有左子树
  • 当前节点既有左子树,也有右子树

进行以上四种情况,进行对应的处理,curr 表示当前要删除的节点,parent 为当前节点的父节点:

  1. 当前节点既没有左子树,也没有右子树。此时删除当前节点,让父节点指向 null
    节点既没有左子树也没有右子树

  2. 当前节点只有左子树,没有右子树。此时只需让左子树移动到当前节点的位置,父节点引用指向左子树即可
     当前节点只有左子树

  3. 当前节点只有右子树,没有左子树。此时只需让右子树移动到当前节点的位置,父节点引用指向右子树即可
    当前节点只有右子树

  4. 当前节点既有左子树,也有右子树。这种情况比较复杂,首先让当前节点右子树上移到当前节点的位置,因为二叉搜索树的特性,做左子树小于右子树的最小值,因此在右子树上一直往左子树走,直到遇到最左边的叶节点,再将当前节点的左子树接在上面
    当前节点既有左子树,也有右子树

2.2 代码


class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if (root == null) {
            return null;
        }
        return process(root, key);
    }

    public TreeNode process(TreeNode root, int key) {
        if (root == null) {
            return null;
        }
        if (root.val < key) {
            root.right = process(root.right, key);
        } else if (root.val > key) {
            root.left = process(root.left, key);
        } else {
            if (root.left == null && root.right == null) {
                return null;
            }
            if (root.left == null) {
                return root.right;
            }
            if (root.right == null) {
                return root.left;
            }
            TreeNode curr = root.right;
            while (curr.left != null) {
                curr = curr.left;
            }
            curr.left = root.left;
            root = root.right;

        }
        return root;
    }
}

2.3 测试结果

通过测试
测试结果

3.总结

  • 这道题分为两步骤:查找节点和删除节点
  • 查找结点使用递归查找更简单一点,使用迭代查找比较复杂
  • 删除节点时需要根据删除节点的左右子树分四种情况进行处理
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值