题目
给定一个二叉搜索树的根节点 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
解题
- 二分搜索树相关知识可以参考 : https://blog.youkuaiyun.com/love905661433/article/details/82981527
- 本题解题如下:
/**
* 450. 删除二叉搜索树中的节点
*/
class Solution {
/**
* 在以root为根节点的二分搜索树中删除节点key
* @param root
* @param key
* @return 返回删除后新的根节点
*/
public TreeNode deleteNode(TreeNode root, int key) {
if (root == null) {
return null;
}
if (key > root.val) {
// key大于当前节点, 从右子树删除节点key, 返回删除节点key后新的根节点
root.right = deleteNode(root.right, key);
return root;
} else if (key < root.val) {
// key小于当前节点, 从左子树删除节点key, 返回删除节点key后新的根节点
root.left = deleteNode(root.left, key);
return root;
} else {
// 左子树为空的情况
if (root.left == null) {
return root.right;
}
// 右子树为空的情况
if (root.right == null) {
return root.left;
}
// 左右子树都不为空的情况
// 从右子树查找当前节点的后继节点
TreeNode successor = findMin(root.right);
// 在右子树中删除后继节点
successor.right = deleteMin(root.right);
successor.left = root.left;
root.left = root.right = null;
return successor;
}
}
/**
* 查找以root为根节点的二分搜索树中的最小值, 用于删除节点时查找后继元素
* @param root
* @return 返回
*/
private TreeNode findMin(TreeNode root){
if (root.left != null) {
return findMin(root.left);
}
return root;
}
/**
* 删除root为根节点的二分搜索树中的最小值
* @param root
* @return 返回删除节点后的树的根节点
*/
private TreeNode deleteMin(TreeNode root){
if (root.left != null) {
root.left = deleteMin(root.left);
return root;
}
return root.right;
}
}