首先需要了解二叉搜索数的特性:
二叉搜索数,父节点一定不小于左子树,一定不大于右子树。
思路:
- 首先先定位到需要删除的节点。
- 如果删除的节点是叶子节点的话,直接返回null就行。
- 如果删除的节点不是叶子结点,但是他的右子树是空的,那就直接返回左子树
- 如果删除的节点不是叶子节点,但是他的左子树是空的,那就直接返回右子树。
- 如果左右都不为空,那就把右子树的最小值,替换为当前节点的值,然后再拼接回树上。
递归实现
/**
* 递归 搜索二叉树的规律
* 父节点的左边一点不大于自己,右边一定不小于自己
*
* @param root
* @param key
* @return
*/
public TreeNode deleteNode(TreeNode root, int key) {
if (root == null){
return null;
}
if (root.val > key){
root.left = deleteNode(root.left, key);
return root;
}
if (root.val < key){
root.right = deleteNode(root.right, key);
}
if (root.val == key){
// 代表单前是叶子节点
if (root.left == null && root.right == null){
return null;
}
if (root.left == null){
return root.right;
}
if (root.right == null){
return root.left;
}
// 找到右子树的最小节点
TreeNode minNode = root.right;
while (minNode.left != null){
minNode = minNode.left;
}
root.right = deleteNode(root.right, minNode.val);
minNode.right = root.right;
minNode.left = root.left;
}
return root;
}
迭代实现
/**
* 使用迭代实现
* @param root
* @param key
* @return
*/
public TreeNode deleteNode2(TreeNode root, int key) {
TreeNode cur = root, curParent = null;
while (cur != null && cur.val != key){
curParent = cur;
if (cur.val > key){
cur = cur.left;
}else {
cur = cur.right;
}
}
if (cur == null){
return root;
}
if (cur.left == null && cur.right == null){
cur = null;
} else if (cur.left == null){
cur = cur.right;
} else if (cur.right == null){
cur = cur.left;
} else {
TreeNode successor = cur.right, successorParent = cur;
while (successor.left != null){
successorParent = successor;
successor = successor.left;
}
if (successorParent.val == key){
successorParent.right = successor.right;
} else {
successorParent.left = successor.right;
}
// 进行数替换
successor.left = cur.left;
successor.right = cur.right;
cur = successor;
}
if (curParent == null){
return cur;
} else {
if (curParent.left != null && curParent.left.val == key) {
curParent.left = cur;
} else {
curParent.right = cur;
}
return root;
}
}
全部代码如下
/**
* @author xnl
* @Description:
* @date: 2022/6/2 22:50
*/
public class Solution {
public static void main(String[] args) {
Solution solution = new Solution();
}
/**
* 递归 搜索二叉树的规律
* 父节点的左边一点不大于自己,右边一定不小于自己
*
* @param root
* @param key
* @return
*/
public TreeNode deleteNode(TreeNode root, int key) {
if (root == null){
return null;
}
if (root.val > key){
root.left = deleteNode(root.left, key);
return root;
}
if (root.val < key){
root.right = deleteNode(root.right, key);
}
if (root.val == key){
// 代表单前是叶子节点
if (root.left == null && root.right == null){
return null;
}
if (root.left == null){
return root.right;
}
if (root.right == null){
return root.left;
}
// 找到右子树的最小节点
TreeNode minNode = root.right;
while (minNode.left != null){
minNode = minNode.left;
}
root.right = deleteNode(root.right, minNode.val);
minNode.right = root.right;
minNode.left = root.left;
}
return root;
}
/**
* 使用迭代实现
* @param root
* @param key
* @return
*/
public TreeNode deleteNode2(TreeNode root, int key) {
TreeNode cur = root, curParent = null;
while (cur != null && cur.val != key){
curParent = cur;
if (cur.val > key){
cur = cur.left;
}else {
cur = cur.right;
}
}
if (cur == null){
return root;
}
if (cur.left == null && cur.right == null){
cur = null;
} else if (cur.left == null){
cur = cur.right;
} else if (cur.right == null){
cur = cur.left;
} else {
TreeNode successor = cur.right, successorParent = cur;
while (successor.left != null){
successorParent = successor;
successor = successor.left;
}
if (successorParent.val == key){
successorParent.right = successor.right;
} else {
successorParent.left = successor.right;
}
// 进行数替换
successor.left = cur.left;
successor.right = cur.right;
cur = successor;
}
if (curParent == null){
return cur;
} else {
if (curParent.left != null && curParent.left.val == key) {
curParent.left = cur;
} else {
curParent.right = cur;
}
return root;
}
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}