题目描述:
??给定一个二叉搜索树的根节点 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
解题思路:
??二叉搜索树有一个很好的性质:左小右大,并且对BST进行中序遍历(左、根、右)得到的序列正好是一个递增序列。本题就是基于BST的性质进行结点的删除。
??前驱结点:Predecessor 代表的是中序遍历序列的前一个节点。即比当前节点小的最大节点,简称前驱节点。先取当前节点的左节点,然后取该节点的右节点,直到右节点为空,则最后指向的节点为前驱节点。
public int predecessor(TreeNode root) {
root = root.left;
while (root.right != null)
root = root.right;
return root;
}
??后继结点:Successor 代表的是中序遍历序列的下一个节点。即比当前节点大的最小节点,简称后继节点。 先取当前节点的右节点,然后一直取该节点的左节点,直到左节点为空,则最后指向的节点为后继节点。
public int successor(TreeNode root) {
root = root.right;
while (root.left != null)
root = root.left;
return root;
}
删除算法:
??(1)如果该节点是叶子节点,则直接删除它:root = null。
??(2)如果该节点只有左子树或者只有右子树,则跳过根,直接返回左子树或右子树。
??(3)如果该节点左右子树都存在,则用它的后继节点的值替代 root.val = successor.val,然后删除后继节点。
代码实现:
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
//BST,左小右大
if(root==null)
return null;
if(key<root.val) //左子树递归
root.left=deleteNode(root.left,key);
else if(key>root.val) //右子树递归
root.right=deleteNode(root.right,key);
else{ //相等,则要删除的就是root
if(root.left==null && root.right==null) //左右都空,叶结点
root=null;
else if(root.right==null) //右为空,返回左
root=root.left;
else if(root.left==null) //左为空,返回右
root=root.right;
else{ //左右都不空,找后继结点代替,右子树最左边
TreeNode parent=root.right;
if(parent.left==null){
root.val=parent.val;
root.right=parent.right;
}else{
TreeNode temp=parent.left;
while(temp.left!=null){
parent=temp;
temp=temp.left;
}
root.val=temp.val;
parent.left=temp.right;
}
}
}
return root;
}
}
原文:https://www.cnblogs.com/gzshan/p/12616412.html