450. 删除二叉搜索树中的节点
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
1、首先找到需要删除的节点;
2、如果找到了,删除它。
思路:递归
二叉搜索树的性质是:
1、若它的左子树不为空,则所有左子树上的值均小于其根节点的值;
2、若它的右子树不为空,则所有右子树上的值均大于其根节点得值;
3、其左右子树也分别为二叉搜索树。
当删除一个节点后,二叉搜索树的性质不变。
当我们找到待删除节点时,有以下几种情况:
一、待删除节点时叶子结点,我们直接删除即可。
if (root.left == null && root.right == null)
return null;
二、若待删除节点不是叶子节点,且有一个子节点为空,我们直接返回另一个不为空的子节点即可。
if (root.left == null) {
return root.right;
}
if (root.right == null) {
return root.left;
}
三、若待删除节点不是叶子节点,且左右子树都不为空,我们可以用左子树的最大值或者是右子树的最小值替换待删除节点。
if (root.left != null && root.right != null) {
// 找到左子树的最大值
TreeNode maxNode = findMax(root.left);
// 把 root 改成 maxNode
root.val = maxNode.val;
// 删除 maxNode
root.left = deleteNode(root.left, root.val);
}
代码实现:
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
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 {
//找到要删除的节点
//两个if把情况一、二都解决了
if (root.left == null) {
return root.right;
}
if (root.right == null) {
return root.left;
}
//待删除节点的两个子节点都不为空,我们找它的左子树的最大值替换
TreeNode maxNode = findMax(root.left);
root.val = maxNode.val;
root.left = deleteNode(root.left, root.val);
//或者找右子树的最小值替换
// TreeNode minNode = findMin(root.right);
// root.val = minNode.val;
// root.right = deleteNode(root.right, root.val);
}
return root;
}
//查找左子树的最大值么
private TreeNode findMax(TreeNode node) {
while (node.right != null) {
node = node.right;
}
return node;
}
//查找右子树的最大值么
// private TreeNode findMin(TreeNode node) {
// while (node.left != null) {
// node = node.left;
// }
// return node;
// }
}