Leetcode450. 删除二叉搜索树中的节点
题目:
给定一个二叉搜索树的根节点 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
题解:
方案一:递归:
- 如果 key>root.valkey > root.valkey>root.val,说明要删除的节点在右子树,root.right=deleteNode(root.right,key)root.right = deleteNode(root.right,key)root.right=deleteNode(root.right,key)。
- 如果 key<root.valkey < root.valkey<root.val,说明要删除的节点在左子树,root.left=deleteNode(root.left,key)root.left = deleteNode(root.left,key)root.left=deleteNode(root.left,key)。
- 如果 key==root.valkey == root.valkey==root.val,则该节点就是我们要删除的节点,则:
1.如果该节点是叶子节点,则直接删除它:root=nullroot = nullroot=null。
2.如果该节点不是叶子节点且有右节点,则用它的后继节点的值替代 root.val=successor.valroot.val = successor.valroot.val=successor.val,然后删除后继节点。
3.如果该节点不是叶子节点且只有左节点,则用它的前驱节点的值替代 root.val=predecessor.valroot.val = predecessor.valroot.val=predecessor.val,然后删除前驱节点。 - 返回 root。
方案二:迭代
java代码:
/**
* 递归
*
* @param root
* @param key
* @return
*/
public static TreeNode deleteNode2(TreeNode root, int key) {
if (root == null) return null;
if (root.value > key) root.left = deleteNode2(root.left, key);
else if (root.value < key) root.right = deleteNode2(root.right, key);
else {
if (root.left == null && root.right == null) root = null;
else if (root.right != null) {
root.value = successor(root);
root.right = deleteNode2(root.right, root.value);
} else {
root.value = predecessor(root);
root.left = deleteNode2(root.left, root.value);
}
}
return root;
}
/**
* 找右子树的最小值
*
* @param root
* @return
*/
public static int successor(TreeNode root) {
root = root.right;
while (root.left != null) root = root.left;
return root.value;
}
/**
* 找左子树的最大值
*
* @param root
* @return
*/
public static int predecessor(TreeNode root) {
root = root.left;
while (root.right != null) root = root.right;
return root.value;
}
迭代:
/**
* 二叉搜索树的中序遍历的序列是递增排序的序列
* 迭代
*
* @param root
* @param key
* @return
*/
public static TreeNode deleteNode(TreeNode root, int key) {
TreeNode cur = root;
TreeNode parent = null;
//找到要删除的节点
while (cur != null && cur.value != key) {
parent = cur;
if (cur.value > key) {
cur = cur.left;
} else if (cur.value < key) {
cur = cur.right;
}
}
if (cur == null) return root;
if (cur.left == null && cur.right == null) {
//删除的节点不是根节点
if (parent != null) {
if (parent.left == cur) {
parent.left = null;
} else {
parent.right = null;
}
} else {
//整个树只有一个节点
return null;
}
//左节点或者右节点其中有一个为null
} else if (cur.left == null || cur.right == null) {
TreeNode sub = cur.left == null ? cur.right : cur.left;
cur.value = sub.value;
cur.left = sub.left;
cur.right = sub.right;
sub.left = null;
sub.right = null;
//左右节点都不为null,找到左子树中的最大值,替换到key节点
} else {
TreeNode sub = cur.left;
//右子树为null
if (sub.right == null) {
cur.left = sub.left;
cur.value = sub.value;
sub.left = null;
} else {
parent = sub;
while (sub.right != null) {
parent = sub;
sub = sub.right;
}
parent.right = sub.left;
cur.value = sub.value;
sub.left = null;
}
}
return root;
}
LeetCode 450:删除二叉搜索树中的节点
本文详细解析了LeetCode 450题——删除二叉搜索树中的节点的解决方案,包括递归和迭代两种方法。通过具体示例,讲解了如何定位并删除目标节点,同时保持二叉搜索树的特性。
1176

被折叠的 条评论
为什么被折叠?



