题干: https://leetcode.com/problems/delete-node-in-a-bst/
这题基本上没什么难度,只要记住一个原则即可,删某节点,调整的原则是将该节点同左子树的最大节点交换,或者同右子树的最小节点交换,才能维持BST属性,并且,如果这个左子树的最大节点不是叶子节点,或者右子树的最小节点不是叶子节点,则这个操作还需要递归地做下去。
另外注意一个小trick就是这里用到的TreeNode结构是不包含parent的,所以为了方便,我自己包装了一个数据结构,记录了parent,以及本节点是parent的左孩子还是右孩子
代码如下:
package com.example.demo.leetcode;
import apple.laf.JRSUIUtils;
/**
* 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 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;
}
}
public class DeleteNodeInBST {
static class NodeAndParent{
TreeNode currentNode;
TreeNode parentNode;
Boolean isLeft;
public NodeAndParent(TreeNode c, TreeNode p, Boolean l){
this.currentNode = c;
this.parentNode = p;
this.isLeft = l;
}
}
public TreeNode deleteNode(TreeNode root, int key) {
// step 1: search the node
NodeAndParent targetNode = searchNode(null, root, key, null);
if(targetNode==null){
//搜索无果
return root;
}
// step 2: mark the node value null, and do the child up recursively
int ret = swapDelete(targetNode);
if(ret==-1){
return null;
}
return root;
}
private int treeHeight(TreeNode node){
if(node==null){
return 0;
}
if(node.left==null && node.right==null){
return 1;
}else{
return 1+Math.max(treeHeight(node.left), treeHeight(node.right));
}
}
private NodeAndParent searchMaxNode(TreeNode node, TreeNode parent ,Boolean isLeft){
if(node.right!=null){
return searchMaxNode(node.right, node,false);
}else{
return new NodeAndParent(node, parent, isLeft);
}
}
private NodeAndParent searchMinNode(TreeNode node, TreeNode parent ,Boolean isLeft){
if(node.left!=null){
return searchMinNode(node.left, node,true);
}else{
return new NodeAndParent(node, parent, isLeft);
}
}
private int swapDelete(NodeAndParent targetNode){
// -1 indicates deleted code
targetNode.currentNode.val = -1;
if(targetNode.currentNode.left!=null){
//如果有左子树,跟左子树最大的节点换,换完targetNode变成新的leftMax位置的节点,继续换
NodeAndParent leftMax = searchMaxNode(targetNode.currentNode.left, targetNode.currentNode, true);
int tmp = targetNode.currentNode.val;
targetNode.currentNode.val = leftMax.currentNode.val;
leftMax.currentNode.val = tmp;
swapDelete(leftMax);
}else if(targetNode.currentNode.right!=null){
//如果有右子树,跟右子树最小节点换
NodeAndParent rightMin = searchMinNode(targetNode.currentNode.right, targetNode.currentNode, false);
int tmp = targetNode.currentNode.val;
targetNode.currentNode.val = rightMin.currentNode.val;
rightMin.currentNode.val = tmp;
swapDelete(rightMin);
}else{
//左右孩子都没
if(targetNode.parentNode!=null){
if(Boolean.TRUE.equals(targetNode.isLeft)){
targetNode.parentNode.left = null;
}else{
targetNode.parentNode.right = null;
}
}else{
return -1;
}
}
return 0;
}
private NodeAndParent searchNode(TreeNode parent, TreeNode root, int key, Boolean isLeft){
if(root==null){
return null;
}
if(key==root.val){
return new NodeAndParent(root, parent, isLeft);
}else if(key<root.val){
return searchNode(root, root.left, key, true);
}else{
return searchNode(root, root.right,key, false);
}
}
public static void main(String[] args) {
}
}