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

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

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

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

首先找到需要删除的节点;
如果找到了,删除它。
在这里插入图片描述
解题思路:

二叉搜索树的特点:中序遍历的序列是递增排序的序列。
这边定义两个函数:successor和predecessor,分别用于查找二叉搜索树当前节点按照中序遍历的后继和前驱节点(前提要求当前节点必须有右、左子树)。具体的函数实现看代码的注释,大概的解释是,后继节点是在右子树的最左侧,前驱节点是左子树的最右侧。
在这里插入图片描述
递归函数deleteNode,用于删除节点,删除分三种情况:
第一种:要删除的值正好是叶节点,直接删除叶节点即可
第二种:当前节点不是叶节点,并且有右子树,找当前节点的后继节点,并且递归删除后继节点
第三种情况:当前节点不是叶子节点,只有左子树,找当前节点的前驱节点,并且递归删除前驱节点
要删除的节点直接用它的后继或前驱节点的值替换,然后再递归删除它的后继或前驱节点,其实递归到最后,删除的是叶节点,具体看代码实现。

代码实现:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    # 按照中序遍历的顺序,查找二叉搜索树当前节点对应的下一个节点
    # 前提是当前节点必须有右子树,即保证查找成功
    def successor(self, root):
        # 将当前节点指向它的右子树
        root = root.right

        # 按照中序二叉查找树的顺序,右子树的最左下节点是当前节点的下一个顺序节点
        # 所以循环结束条件是当前节点是否还有左子树
        while root.left:
            root = root.left
        return root.val
        
    # 按照中序遍历的顺序,查找二叉搜索树当前节点对应的上一个节点
    # 前提是当前节点必须有左子树,即保证查找成功
    def predecessor(self, root):
        # 将当前节点指向它的左子树
        root = root.left

        # 按照中序二叉查找树的顺序,左子树的最右下节点是当前节点的上一个顺序节点
        # 所以循环结束条件是当前节点是否还有右子树
        while root.right:
            root = root.right
        return root.val

    def deleteNode(self, root: TreeNode, key: int) -> TreeNode:
        if not root:
            return None
            
        # 删除分三种情况
        # 要删除的值在右子树中
        if key > root.val:
            root.right = self.deleteNode(root.right, key)

        # 要删除的值在左子树中
        elif key < root.val:
            root.left = self.deleteNode(root.left, key)

        # 要删除的值就是当前值
        # 这时候也分三种情况
        else:
            # 第一种:要删除的值正好是叶节点,直接删除叶节点即可
            if not (root.left or root.right):
                # 直接将该节点置空
                root = None
            # 第二种:当前节点不是叶节点,并且有右子树
            # 找当前节点的后继节点,并且递归删除后继节点
            elif root.right:
                # 将当前节点的值赋值为后继几点的值
                root.val = self.successor(root)
                # 递归删除右子树的后继节点
                root.right = self.deleteNode(root.right, root.val)
            # 第三种情况:当前节点不是叶子节点,只有左子树
            # 找当前节点的前驱节点,并且递归删除前驱节点
            else:
                root.val = self.predecessor(root)
                root.left = self.deleteNode(root.left, root.val)
        
        return root

参考文献:
https://leetcode-cn.com/problems/delete-node-in-a-bst/solution/shan-chu-er-cha-sou-suo-shu-zhong-de-jie-dian-by-l/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值