给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
解题思路
在二叉搜索树中,每个节点有一个值,并且左子树中所有节点的值都小于根节点的值,右子树中所有节点的值都大于根节点的值。删除节点时,主要有以下几种情况需要考虑:
- 要删除的节点没有子节点(叶子节点):直接删除该节点。
- 要删除的节点只有一个子节点:删除该节点,并将其唯一的子节点接到其父节点上。
- 要删除的节点有两个子节点:找到右子树中的最小节点(即中序后继节点),用该节点的值替换要删除的节点,然后递归地删除这个最小节点。
完整代码如下:
class Solution:
def deleteNode(self, root, key):
if root is None:
return root
if root.val == key:
if root.left is None and root.right is None:
return None
elif root.left is None:
return root.right
elif root.right is None:
return root.left
else:
cur = root.right
while cur.left is not None:
cur = cur.left
cur.left = root.left
return root.right
if root.val > key:
root.left = self.deleteNode(root.left, key)
if root.val < key:
root.right = self.deleteNode(root.right, key)
return root
if root is None:
return root
如果当前节点为空,直接返回 None
,表示树没有变化。
if root.val == key:
如果当前节点的值等于 key
,说明找到了需要删除的节点。
if root.left is None and root.right is None:
return None
如果要删除的节点是叶子节点(即没有左子树和右子树),直接返回 None
,表示删除这个节点。
elif root.left is None:
return root.right
如果要删除的节点没有左子树,但有右子树,直接返回右子树,表示将右子树提升为新的子树。
elif root.right is None:
return root.left
如果要删除的节点没有右子树,但有左子树,直接返回左子树,表示将左子树提升为新的子树。
else:
cur = root.right
while cur.left is not None:
cur = cur.left
cur.left = root.left
return root.right
如果要删除的节点既有左子树又有右子树:
- 找到右子树中最左边的节点(即右子树中的最小节点)。
- 将这个最小节点的左子树指向要删除节点的左子树。
- 返回当前节点的右子树作为新根节点(因为最小节点是右子树的一部分)。
if root.val > key:
root.left = self.deleteNode(root.left, key)
如果当前节点的值大于 key
,说明要删除的节点在左子树中。递归地在左子树中继续查找并删除节点。
if root.val < key:
root.right = self.deleteNode(root.right, key)
如果当前节点的值小于 key
,说明要删除的节点在右子树中。递归地在右子树中继续查找并删除节点。