LeetCode 450 Medium BST 节点删除 Python

75 篇文章 0 订阅
72 篇文章 0 订阅

    XiaoXiang Method

    算法:?

    思路

        先找到节点,然后再对要删除的节点进行处理

        找到节点好说,用BST的性质找就好了

        主要在于如何处理

        这里的方法比较笨也比较麻烦,

            1. 先确定当前root是prev的左孩子还是右孩子,后面重构prev要用

            2. 如果左子树为空,将右子树顶上来,如果右子树为空,左子树顶上来

            3. 左右子树都不为空时,将右子树的最左节点替换为当前root节点,这样处理后,仍是BST

❗️右子树的最左节点,一定大于原root的所有左子树节点,也一定小于原root的所有右子树节点,所以用右子树最左节点替换!

                而右子树又分几种情况:

                    1.右子树是叶子节点,直接替换

                    2.右子树有左子树

                        找到最左节点p和最左节点的上一个节点p_prev

                        如果p_prev != root                       

                        root-> 5
                                \
                                8 <- p_prev
                              /  \
                         p-> 6    9
                              \
                               7

                            令root.val = p.val,并且p_prev.left = p.right

                        否则                               

                                8 -> root(p_prev)
                              /  \
                          p->6    9

                            令root.right = p.right

        调整完右子树后,将右子树与prev再连接起来

        注意如果删除的是整棵树的根节点,最后要直接return adjust的结果,调整后的节点就是根节点,

        否则返回原root,此时原root已被修改

    注意❗️:

        不能在递归中进行adjust操作,否则的话,如果操作的是根节点,根节点的变动不会被引用赋值传到外面!

        因为递归栈的原因!

        当前层root = None,然后传导到上一层调用之的地方,root = 3,下一层修改的root = None被抹除了!

        所以我这里分开来处理来避免无法将值带出的问题,其实主要是当要修改的就是顶层根节点的时候会出这个问题!

        先findeNode找到node和prev,在adjuest对node和prev做修改

        最后返回整个root

 

    复杂度分析

        时间:找节点logN,调整节点OK

        空间:logN,递归栈

def deleteNode(self, root, key):

    def adjust(root, prev):

        left = prev != None and prev.left == root

        right = prev != None and prev.right == root

        if root.left == None:

            root = root.right

        elif root.right == None:

            root = root.left

        else:

            p = root.right

            if p.left == None and p.right == None:

                root.val = p.val

                root.right = None

            else:

                p_prev = root

                while p.left:

                    p_prev = p

                    p = p.left

                if p_prev != root:

                    p_prev.left = p.right

                else:

                    p_prev.right = p.right

                root.val = p.val

            del p

        if left:

            prev.left = root

        elif right:

            prev.right = root

        return root



    def findNode(root, prev):

        if root == None:

            return None, prev

        if root.val == key:

            return root, prev

        if key < root.val:

            return findNode(root.left, root)

        else:

            return findNode(root.right, root)



    node, prev = findNode(root, None)

    if node != None:

        curr = adjust(node, prev)

        if prev == None:

            return curr

    return root

    Disscussion Method

    思路:

        和上述 XiaoXiang Method 一样!

        但是代码写得更漂亮!

        好好品一下

def deleteNode1(self, root, key):   

    if not root:

        return None

    if key > root.val:

        # 注意体会一下运用递归重新构建二叉树的过程,

        # 通过这种方式,可以将二叉树从下往上重新构建一遍,最后返回根元素

        root.right = self.deleteNode(root.right, key)

        return root

    elif key < root.val:

        root.left = self.deleteNode(root.left, key)

        return root

    else:

        # 待删除如果左子树为空

        if not root.left:

            rightNode = root.right

            root.right = None

            # 把右侧节点返回去,重新挂回树上

            return rightNode

        # 待删除如果右子树为空

        if not root.right:

            leftNode = root.left

            root.left = None

            return leftNode

        # 如果左右子树都存在的情况下

        # 找到待删除节点右子树中的最小元素,然后替换待删除元素

        successor = self.minimum(root.right)

        # 删除右子树中的最小值,并返回右子树的根节点

        successor.right = self.removeMin(root.right)

        successor.left = root.left

        return successor



def minimum(self, root):

    if not root.left:

        return root

    return self.minimum(root.left)



def removeMin(self, root):

    if not root.left:

        rightNode = root.right

        root.right = None

        return rightNode

    root.left = self.removeMin(root.left)

    return root

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值