题目描述
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。一般来说,删除节点可分为两个步骤:首先找到需要删除的节点,如果找到了,删除它。
解析
这题需要知道删除的三种情况以及一个小技巧。删除分无子树、单子树和双子树的情况,前两种比较简单,第三种需要找到删除节点的右边最小节点替代它,在删除右边最小节点转为上两种情况。然后是对于根节点,由于没有父节点,要么单独判断要么就可以加一个哨兵节点。
public TreeNode deleteNode(TreeNode root, int key) {
TreeNode dummy = new TreeNode(0);
dummy.left = root;
TreeNode parent = dummy, node = root;
boolean isLeft = true;
// 查找节点
while (node != null && node.val != key) {
parent = node;
if (key < node.val) {
node = node.left;
isLeft = true;
} else {
node = node.right;
isLeft = false;
}
}
if (node == null) return dummy.left; // 没找到直接返回
// 删除找到的节点
if (node.left != null && node.right != null) { // 两个子节点
TreeNode successor = node.right, successorParent = node;
while (successor.left != null) {
successorParent = successor;
successor = successor.left;
}
node.val = successor.val;
node = successor;
parent = successorParent;
isLeft = (successorParent.left == successor);
}
TreeNode replacement = (node.left != null) ? node.left : node.right;
if (isLeft) {
parent.left = replacement;
} else {
parent.right = replacement;
}
return dummy.left;
}