版权声明:本文为博主原创文章,未经博主允许不得转载。有事联系:[email protected] https://blog.csdn.net/qq_17550379/article/details/82344213
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
- 首先找到需要删除的节点;
- 如果找到了,删除它。
说明: 要求算法时间复杂度为 O(h),h 为树的高度。
示例:
root = [5,3,6,2,4,null,7]
key = 3
5
/ \
3 6
/ \ \
2 4 7
给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
5
/ \
4 6
/ \
2 7
另一个正确答案是 [5,2,6,null,4,null,7]。
5
/ \
2 6
\ \
4 7
解题思路
这是一个非常经典的问题,我们将通过hibbard deletion
来解决这个问题。主要分成如下三种情况:
- 被删除的节点没有子节点
- 被删除的节点没有左孩子或右孩子
- 被删除的节点包含左右孩子
0x01 被删除的节点没有左右孩子
由于它没有子节点,我们直接将该节点置为
null
即可。
0x02 被删除的节点没有左孩子或右孩子
无论被删除的节点是包含左孩子还是右孩子,我们直接将该节点唯一的孩子链接到其父节点,然后删除该节点即可。
0x03 被删除的节点包含左右孩子
这是三种情况中最复杂的情况,我们有两种策略:一种是从左子树中选择出左子树中的最大值,用来替换要删除的节点;另一种是,从右子树中选择出右子树中的最小值,用来替换要删除的节点。我们这里使用第二种策略,也就是使用
21
替换删除元素
20
。
这个问题中,我们会面临这样的两个问题:
求右子树最小值
def minimum(self, root): if not root.left: return root return self.minimum(root.left)
删除右子树最小值
def removeMin(self, root): if not root.left: right = root.right return right root.left = self.removeMin(root.left) return root
剩下的问题就是对这些问题的整合
class Solution:
def minimum(self, root):
if not root.left:
return root
return self.minimum(root.left)
def removeMin(self, root):
if not root.left:
right = root.right
return right
root.left = self.removeMin(root.left)
return root
def deleteNode(self, root, key):
"""
:type root: TreeNode
:type key: int
:rtype: TreeNode
"""
if not root:
return None
if key < root.val:
root.left = self.deleteNode(root.left, key)
return root
elif key > root.val:
root.right = self.deleteNode(root.right, key)
return root
else:
if not root.left:
return root.right
if not root.right:
return root.left
tmp = self.minimum(root.right)
tmp.right = self.removeMin(root.right)
tmp.left = root.left
return tmp
同样的,我们对于递归求解的问题都希望尝试是否可以通过迭代去求解。
class Solution(object):
def deleteNode(self, root, key):
"""
:type root: TreeNode
:type key: int
:rtype: TreeNode
"""
p = root
p_parent = None
while p and p.val != key:
p_parent = p
if p.val > key:
p = p.left
else:
p = p.right
if not p:
return root
p_right_parent = p
p_right = p.right
if not p_right:
if not p_parent:
return p.left
if p_parent.left == p:
p_parent.left = p.left
else:
p_parent.right = p.left
else:
while p_right.left:
p_right_parent = p_right
p_right = p_right.left
p.val = p_right.val
if p_right_parent.left == p_right:
p_right_parent.left = p_right.right
else:
p_right_parent.right = p_right.right
return root
reference:
http://javabypatel.blogspot.com/2015/08/delete-a-node-from-binary-search-tree-in-java.html
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!