删除二叉搜索树中的节点
题目链接:https://leetcode-cn.com/problems/delete-node-in-a-bst/
题目大意:删除指定key的节点,返回root
分析:树是二叉搜索树,要求返回后仍然保持搜索树的位置
二叉搜索树:根节点值大于左孩子值,根节点值小于右孩子值
根据待删除节点的情况,我们可以采取不同的措施
-
如果目标节点大于当前节点值,则去右子树中删除;
-
如果目标节点小于当前节点值,则去左子树中删除;
-
如果目标节点就是当前节点,分为以下三种情况:
- 其无左子:其右子顶替其位置,删除了该节点;
- 其无右子:其左子顶替其位置,删除了该节点;
- 其左右子节点都有:其左子树转移到其右子树的最左节点的左子树上,然后右子树顶替其位置,由此删除了该节点。
第三种情况如图:
- 时间复杂度:O(H),H是树的高度,寻找目标节点最坏情况需要O(H),删除操作最坏情况也需要O(H);
- 空间复杂度:O(H),递归栈的深度最坏情况为树的高度;
func deleteNode(root *TreeNode, key int) *TreeNode {
if root==nil{
return nil
}
if key>root.Val{
// 目标值大于当前值,则去当前节点的右子树中删除
root.Right=deleteNode(root.Right,key)
}else if key<root.Val{
// 目标值小于当前值,则去当前节点的左子树中删除
root.Left=deleteNode(root.Left,key)
}else if key==root.Val{
// 目标节点等于当前值,分析当前节点的左右孩子情况,采取不同策略
if root.Left==nil{
// 待删除节点的左孩子为空,则右孩子顶替待删除节点位置
root=root.Right
}else if root.Right==nil {
// 待删除节点的右孩子为空,则左孩子顶替待删除节点位置
root=root.Left
}else if root.Right!=nil&&root.Left!=nil {
// 待删除节点的左右孩子都不为空,现在处理其左右孩子
// 第一步:寻找待删除root节点的右子树的最左节点node
node:=root.Right
for node.Left!=nil{
node=node.Left
}
// 第二步:root左子树转移到node的左子树上,仍然保存搜索树性质
node.Left=root.Left
// 第三步:root的右子树顶替root位置
root=root.Right
}
}
return root
}