1.题目描述:
给定一个二叉搜索树的根节点root和一个值key,删除二叉搜索树中的key对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。一般来说,删除节点可分为两个步骤:首先找到需要删除的节点;如果找到了,删除它。
2.自己写的裹脚布代码:
思路和插入操作leetcode701. 二叉搜索树中的插入操作差不多,二叉搜索树的删除节点较为复杂分三种情况:①删除叶子节点:直接删除。②删除只有一颗子树的节点:子承父业。③删除有两颗子树的节点:记录删除节点右子树的最小值,递归删除最小值节点,将原来待删除节点的值置为最小值。细节就直接看代码注释了:
/**
* Definition for a binary tree node.
* public 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;
* }
* }
*/
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if (root == null) return root;
TreeNode keyNode = getKeynode(root, key);
TreeNode parent = getParent(root, key);
if (keyNode == null) return root;//删除根节点单独写
if (keyNode == root) {
if (keyNode.left == null && keyNode.right == null) return null;
else if (keyNode.left == null) return keyNode.right;
else if (keyNode.right == null) return keyNode.left;
else {
TreeNode minNode = getMinnode(keyNode.right);
deleteNode(root, minNode.val);
keyNode.val = minNode.val;
}
} else {
if (keyNode.left == null && keyNode.right == null) {//删除叶子节点
if (parent.left == keyNode) parent.left = null;
else parent.right = null;
} else if (keyNode.left == null) {//删除单子树节点
if (parent.left == keyNode) parent.left = keyNode.right;
else parent.right = keyNode.right;
} else if (keyNode.right == null) {
if (parent.left == keyNode) parent.left = keyNode.left;
else parent.right = keyNode.left;
} else {//删除双子树节点
TreeNode minNode = getMinnode(keyNode.right);
deleteNode(root, minNode.val);
keyNode.val = minNode.val;
}
}
return root;
}
//找到待删除的节点
public TreeNode getKeynode(TreeNode root, int key) {
TreeNode temp = root;
while (temp != null) {
if (temp.val > key) temp = temp.left;
else if (temp.val < key) temp = temp.right;
else return temp;
}
return null;
}
//找到待删除结点的父节点,若待删除为root节点则返回null
public TreeNode getParent(TreeNode root, int key) {
TreeNode temp = root;
TreeNode parent = null;
while (temp != null) {
if (temp.val > key) {
parent = temp;
temp = temp.left;
}
else if (temp.val < key) {
parent = temp;
temp = temp.right;
}
else return parent;
}
return null;
}
//找到最小值节点
public TreeNode getMinnode(TreeNode root) {
TreeNode temp = root;
while (temp.left != null) temp = temp.left;
return temp;
}
}
3.递归:
依然利用递归函数的返回值来完成把节点从二叉树中移除的操作,绝。
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
root = delete(root, key);
return root;
}
private TreeNode delete(TreeNode root, int key) {
if (root == null) return null;
if (root.val > key) {
root.left = delete(root.left, key);
} else if (root.val < key) {
root.right = delete(root.right, key);
} else {
if (root.left == null) return root.right;
if (root.right == null) return root.left;
TreeNode temp = root.right;
while (temp.left != null) temp = temp.left;
root.val = temp.val;
root.right = delete(root.right, temp.val);
}
return root;
}
}
二刷:
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if (root == null) return root;
if (root.val > key) root.left = deleteNode(root.left, key);
else if (root.val < key) root.right = deleteNode(root.right, key);//这里必须要使用else if,否则root.val>key(后无return语句)还会进入else语句中
else {
if (root.left == null) return root.right;
if (root.right == null) return root.left;
TreeNode temp = root.right;
while (temp.left != null) {
temp = temp.left;
}
//改变树的高度:直接将root左子树拼接到右子树的最小节点左子树
temp.left = root.left;
root = root.right;//删除了root节点,将其右子树代替返回
//不改变树的高度:
//root.val = temp.val;//节点值被右子树最小节点替换,变相删除
//root.right = deleteNode(root.right, root.val);//递归拼接删除最小节点的右子树
}
return root;
}
}