Given a root node reference of a BST and a key, delete the node with the given key in the BST. Return the root node reference (possibly updated) of the BST.
Basically, the deletion can be divided into two stages:
Search for a node to remove.
If the node is found, delete the node.
Note: Time complexity should be O(height of tree).
Example:
root = [5,3,6,2,4,null,7]
key = 3
5
/
3 6
/ \
2 4 7
Given key to delete is 3. So we find the node with value 3 and delete it.
One valid answer is [5,4,6,2,null,null,7], shown in the following BST.
5
/
4 6
/
2 7
Another valid answer is [5,2,6,null,4,null,7].
5
/
2 6
\
4 7
1
分析:BST删除一个节点后,仍要保持BST的特性. 删除一个节点本质上说,就是使用这个节点的中序遍历的直接前驱或者直接后继来代替他
删除一个节点分为四种情况
1)待删除节点p是个叶子节点,那么直接删除他即可
2)待删除节点p只有右子树而无左子树,此时只需p的右子树根节点代替p即可
3)待删除节点p只有左子树而无右子树,此时只需p的左子树根节点代替p即可
4)待删除节点p左右子树都不为空.可以有两种方法处理
A,用p的左子树的最右边节点代替
B,用p的右子树的最左边节点代替
public class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if(root == null){
return root;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
//待删除节点,初始化为根节点进行查找
TreeNode delNode = root;
//待删除节点的双亲节点
TreeNode delParentNode = null;
//查找待删除节点以及他的双亲节点
while(delNode != null && delNode.val != key){
delParentNode = delNode;
if(key < delNode.val){
delNode = delNode.left;
}else{
delNode = delNode.right;
}
}
if(delNode == null){//说明不存在值为key的待删除节点
return root;
}else if(delNode.left == null && delNode.right == null){//如果是待删除节点是叶子节点,直接删除即可
if(delParentNode == null){
//说明需要删除根节点(此种情况,二叉排序树只有一个根节点)
return delParentNode;
}else{
if(delParentNode.left == delNode){
//待删除节点位于双亲节点的左子树
delParentNode.left = null;
}else{
//待删除节点位于双亲节点的右子树
delParentNode.right = null;
}
return root;
}
}else if(delNode.left != null && delNode.right == null){//待删除节点只有左子树,没有右子树,直接使用左子树代替即可
if(delParentNode == null){
//说明该二叉排序树只有一个根节点,且需要删除
TreeNode newRoot = delNode.left;
delNode.left = null;
return newRoot;
}else{
if(delParentNode.left == delNode){
delParentNode.left = delNode.left;
delNode.left = null;
} else{
delParentNode.right = delNode.left;
delNode.left = null;
}
return root;
}
}else if(delNode.left == null && delNode.right != null){//待删除节点只有右子树,没有左子树,直接使用右子树代替即可
if(delParentNode == null){
//说明该二叉排序树只有一个根节点,且需要删除
TreeNode newRoot = delNode.right;
delNode.right = null;
return newRoot;
}else{
if(delParentNode.left == delNode){
delParentNode.left = delNode.right;
delNode.right = null;
} else{
delParentNode.right = delNode.right;
delNode.right = null;
}
return root;
}
}else{//待删除节点具有左右子树,可以使用待删除节点左子树最右节点代替或者使用待删除节点右字数(也就是使用其中序的直接前驱或者直接后继代替.这里使用左子树最右边的节点)
TreeNode rightParent = delNode;
TreeNode rightNode = delNode.left;
while(rightNode.right != null){
rightParent = rightNode;
rightNode = rightNode.right;
}
//删除最右边节点rightNode
if(rightParent.left == rightNode){
rightParent.left = rightNode.left;
}else{
rightParent.right = rightNode.left;
}
rightNode.left = null;
//将待删除节点的值置换为最右边节点rightNode的值
delNode.val = rightNode.val;
return root;
}
}
}