Leetcode 450. Deleting Nodes in Binary Search Tree-Simplified Iterative Method

Given the root node root of a binary search tree and a value key, delete the node corresponding to the key in the binary search tree, and ensure that the nature of the binary search tree remains unchanged. Returns a reference to the root node of the binary search tree (which may be updated).

Generally speaking, deleting a node can be divided into two steps:

First find the node that needs to be deleted;
if found, delete it.
Explanation: The time complexity of the algorithm is required to be O(h), and h is the height of the tree.

Example:

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

The problem is simply to delete a node in the binary search tree.

One, iterative method

If you consider it according to the situation, the idea is clear and simple:

  1. When the node to be deleted has no child nodes:
    then directly set the pointer to the node to be deleted and leave it blank
  2. When the node to be deleted has a child node:
    Point the pointer to the node to be deleted to the son of the node to be deleted (you need to judge whether it is the left son or the right son)
  3. The node to be deleted has two child nodes:
    find the minimum value in the right subtree of the node to be deleted, and replace the node to be deleted.

We know that if you want to delete a node, you must find this node first. If you find iteratively, you must use two pointers, one for the location you are looking for, and the other to record the parent node of this location (because When deleting a node, do you need to know the parent node of this node)

So the java code is as follows:

(1) Find the point to be deleted:

TreeNode p=root;//利用p去遍历,保留root不动,最后得返回root
TreeNode pp=null;//p的父节点

while(p!=null&&p.val!=key){
    
    
    pp=p;
    if(key<p.val) p=p.left;
    else p=p.right;
}//此循环结束后,p就是待删除的节点,pp是p的父节点

if(p==null) return root;//没有找到待删除的值

(2) The node to be deleted has no child nodes

//如果p没有孩子,则直接把pp指向置空
if(p.left==null&&p.right==null) {
    
    
if(pp.left==p) pp.left=null;
if(pp.right==p) pp.right=null;
}

(3) When the node to be deleted has a child node:

 //如果p只有一个孩子,那直接把孩子换上来即可
TreeNode child=null;
if(p.left==null&&p.right!=null) child=p.right;
if(p.left!=null&&p.right==null) child=p.left;
if(pp.left==p) pp.left=child;
if(pp.right==p) pp.right=child;

(4) The node to be deleted has two child nodes:

//如果p有左右子树,那就将其右子树的最小值来替换p
        if(p.left!=null&&p.right!=null){
    
    
            TreeNode rp=p.right;
            TreeNode rpp=p;
            while(rp.left!=null){
    
    
                rpp=rp;
                rp=rp.left;
            }//循环结束后,rp就是要找的右子树的最小值,rpp是其父节点
            //将rpp指向rp的指针置空
            if(rpp.left==rp) rpp.left=null;
            if(rpp.right==rp) rpp.right=null;
            //将待删除节点的val换上
            p.val=rp.val;
        }

But, like the above, there are a lot of ifs to judge the various situations that appear, which is very cumbersome.
I found the condensed wording of the Great God:
Observing the above, there must be a process of emptying the pointer and repointing the pointer.
So the Great God’s method is to combine these two steps, so that the three situations share a set of pointers emptying and re-pointing process.
The java code is as follows:

/**
 * 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) {
    
    
        TreeNode p=root;//利用p去遍历,保留root不动,最后得返回root
        TreeNode pp=null;//p的父节点

        while(p!=null&&p.val!=key){
    
    
            pp=p;
            if(key<p.val) p=p.left;
            else p=p.right;
        }//此循环结束后,p就是待删除的节点,pp是p的父节点
        
        if(p==null) return root;//没有找到待删除的值



        //如果p有左右子树,那就将其右子树的最小值来替换p
        if(p.left!=null&&p.right!=null){
    
    
            TreeNode rp=p.right;
            TreeNode rpp=p;
            while(rp.left!=null){
    
    
                rpp=rp;
                rp=rp.left;
            }//循环结束后,rp就是要找的右子树的最小值,rpp是其父节点
            
            //将待删除节点的val换上
            p.val=rp.val;
            //将rpp指向rp的指针置空
            //if(rpp.left==rp) rpp.left=null;
            //if(rpp.right==rp) rpp.right=null;
            p=rp;
            pp=rpp;
        }
        //!!!此方法的这里不好理解!!!
        //删除节点是叶子节点或仅有一个子节点
        TreeNode child;//p的子节点
        if(p.left!=null) child=p.left;
        else if(p.right!=null) child=p.right;
        else child=null;

        if(pp==null) root=child;//删除的是根节点
        else if(pp.left==p) pp.left=child;
        else pp.right=child;

        return root;
        
    }
}

Two, recursive method

/**
 * 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 null;

        if(key<root.val){
    
    
            root.left=deleteNode(root.left,key);
        }else if(key>root.val){
    
    
            root.right=deleteNode(root.right,key);
        }else{
    
    //root节点正是待删除的值
            if(root.left==null){
    
    //当前节点没有左子树
                return root.right;
            }else if(root.right==null){
    
    
                return root.left;
            }else{
    
    //当前节点有左右子树,将左子树直接放到右子树的最小节点左侧即可
                //找右子树的最小节点
                TreeNode minP=root.right;
                while(minP.left!=null){
    
    
                    minP=minP.left;
                }//minP即为右子树的最小节点
                minP.left=root.left;
                return root.right;
            }
        }
        return root;       
    }
}

Guess you like

Origin blog.csdn.net/xiaohaigary/article/details/112290753