二叉搜索树的删除

450.删除二叉搜索树中的节点

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

  1. 首先找到需要删除的节点;
  2. 如果找到了,删除它。

示例 1:

img

1
2
3
4
5
输入:root = [5,3,6,2,4,null,7], key = 3
输出:[5,4,6,2,null,null,7]
解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
另一个正确答案是 [5,2,6,null,4,null,7]。

示例 2:

1
2
3
输入: root = [5,3,6,2,4,null,7], key = 0
输出: [5,3,6,2,4,null,7]
解释: 二叉树不包含值为 0 的节点

示例 3:

1
2
输入: root = [], key = 0
输出: []

提示:

  • 节点数的范围 [0, 104].
  • -105 <= Node.val <= 105
  • 节点值唯一
  • root 是合法的二叉搜索树
  • -105 <= key <= 105
替换法

1.删除的节点是叶子节点直接删除

2.删除节点左子树不为空,右子树为空,用左子树替补

3.删除节点右子树不为空,左子树为空,用右子树替补

4.删除节点左右子树都不为空,找到右子树最左节点,用其值替换删除节点的值,然后删除右子树上的该节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if(root == null) return null; //找不到删除节点直接返回null

if(root.val==key){ //找到删除的结点
if(root.left==null&&root.right==null){ //删除节点是叶子节点,直接删除
return null;
}
else if(root.left==null&&root.right!=null){//删除节点右孩子不为空,右孩子补位
return root.right;
}
else if(root.left!=null&&root.right==null){//删除节点左孩子不为空,左孩子补位
return root.left;
}
else{//找右子树的最左结点,将其值替换到要删除的结点,然后再删除该结点
TreeNode node = root.right;
while(node.left!=null){
node = node.left;
}
root.val = node.val;
root.right = deleteNode(root.right, node.val); //右子树上删除最左结点

//或者直接将root的左子树加入到最左节点的左子树,然后返回root的右子树
//node.left = root.left;
//return root.right;
}
}else if(root.val > key){
root.left = deleteNode(root.left, key);
}else{
root.right = deleteNode(root.right, key);
}
return root;
}
}
直接变换法

前三种情况同替换法相同

第四种情况为:

将待删除结点的左子树插入到右子树的最左结点的左孩子上,然后右子树替补删除节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if(root==null) return null;
if(root.val==key){ //找到删除的结点
if(root.left==null&&root.right==null){//删除节点是叶子节点,直接删除
return null;
}
else if(root.left==null&&root.right!=null){//删除节点右孩子不为空,右孩子补位
return root.right;
}
else if(root.left!=null&&root.right==null){//删除节点左孩子不为空,左孩子补位
return root.left;
}
else{//找右子树的最左孩子,该结点的左子树变为被删除结点的左子树,然后用右子树替补
TreeNode node = root.right;
while(node.left!=null){
node = node.left;
}
node.left = root.left;
root = root.right;
return root;
}
}
if(root.val>key) root.left = deleteNode(root.left,key);
if(root.val<key) root.right = deleteNode(root.right,key);
return root;
}
}

迭代法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if(root == null) return root;

TreeNode cur = root;
TreeNode pre = null;//保存要删除节点的父节点
while(cur != null){//找父节点
if(cur.val == key){
break;
}
pre = cur;
if(cur.val > key){
cur = cur.left;
}
else{
cur = cur.right;
}
}
if(pre == null){//要删除的节点是头节点
return deleteOneNode(root);
}
if(pre.left == cur && pre.left != null){//要删除节点是pre的左节点
pre.left = deleteOneNode(cur);
}
if(pre.right == cur && pre.right != null){//要删除节点是pre右节点
pre.right = deleteOneNode(cur);
}
return root;
}

//删除节点的操作
public TreeNode deleteOneNode(TreeNode root){
if(root == null) return null;
if(root.left==null&&root.right==null){//删除节点是叶子节点,直接删除
return null;
}
else if(root.left==null&&root.right!=null){//删除节点右孩子不为空,右孩子补位
return root.right;
}
else if(root.left!=null&&root.right==null){//删除节点左孩子不为空,左孩子补位
return root.left;
}
else{//找右子树的最左孩子,该结点的左子树变为被删除结点的左子树,然后用右子树替补
TreeNode node = root.right;
while(node.left!=null){
node = node.left;
}
node.left = root.left;
root = root.right;
return root;
}
}

}

二叉搜索树的删除
http://example.com/2023/04/18/算法/二叉树/27. 二叉搜索树的删除/
作者
PALE13
发布于
2023年4月18日
许可协议