LeetCode delete nodes in the binary search tree (450 questions) recursive and non-recursive

LeetCode delete a node in the binary search tree

@author:Jingdai
@date:2020.12.06

Topic description (450 questions)

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).

Topic analysis

For a binary search tree, to delete a node in the tree, there are three situations.

Case 1: If the node to be deleted is a leaf node, such as node 12 in the figure, it can be deleted directly.

Insert picture description here

Case 2: If the node to be deleted has only one subtree, such as node 5 in the figure, you can just lift the subtree of that node.

Insert picture description here

Case 3: If the node to be deleted has two children, such as node 15 in the graph. In this case, in order to prevent the structure of the search binary tree from being destroyed, it is necessary to find the smallest node from the right subtree of the deleted node, assign the value of this node to the deleted node, and then delete the smallest node in the right subtree. (Of course, you can find the largest node from the left subtree of the deleted node)

Insert picture description here

Idea and code

There are two ways to achieve it, one is recursive and the other is non-recursive.

Recursive method

We first look at the definition of the function, delete a node, and return a reference to the root node of the binary search tree (which may be updated).

If the value of the key is greater than the value of the current node, it means that it should be deleted from the right subtree . The root node of the right subtree after the key is deleted is returned, and the result is assigned to the right subtree of the current node. which is:root.right = deleteNode(root.right, key);

If the value of the key is smaller than the value of the current node, it means that it should be deleted from the left subtree . The root node of the left subtree after the key is deleted is returned, and the result is assigned to the left subtree of the current node. which is:root.left = deleteNode(root.left, key);

If the value of the key is equal to the value of the current node, it means that it should be deleted. Delete it according to the three situations in the problem analysis.

The complete code is as follows.

public TreeNode deleteNode(TreeNode root, int key) {
    
    
    if (root == null)
        return null;

    if (key == root.val) {
    
    
        // 1.leaf
        if (root.left == null && root.right == null) {
    
    
            return null;
        } else if (root.left == null) {
    
     // 2.left is null
            return root.right;  
        } else if (root.right == null) {
    
     // 3.right is null
            return root.left;
        } else {
    
     // 4.left/right r not null
            TreeNode rightTreeMin = root.right;
            while (rightTreeMin.left != null) {
    
    
                rightTreeMin = rightTreeMin.left;
            }
            root.val = rightTreeMin.val;
            root.right = deleteNode(root.right, rightTreeMin.val);
        }
    } else if (key > root.val) {
    
    
        root.right = deleteNode(root.right, key);
    } else {
    
    
        root.left = deleteNode(root.left, key);
    }
    return root;
}

Non-recursive method

The idea is still similar. When the value of the key is greater than the value of the current node, it will search in the right subtree; when the value of the key is smaller than the value of the current node, it will search in the left subtree until the node to be deleted is found. But note that the non-recursive method also needs to record the parent node of the current node for the final deletion, because the recursive method is processed in the upper layer of the recursive function, so there is no need to record. When the left and right subtrees of the deleted node are not empty, there are two situations for the parent node. As shown left, when you want to delete a node 20, the smallest node is the right child curof the right child, preequal cur, then delete the right sub-tree node should get a minimum preof the right child equal to the right child node of the right subtree minimum, namely: pre.right = rightTreeMin.right; as shown in the right, when the right sub-tree node is not a minimum curwhen the right child, such as deleting a node 15, deleting the right sub-tree node should get a minimum preof left and right child equal to the smallest child right child tree nodes, namely: pre.left = rightTreeMin.right.

Insert picture description here

At the same time, non-recursive method to delete a node is the root node also special judge, otherwise prethere will be a null pointer exception. When the root judge, regardless of left and right sub-tree is not empty, because this situation would be prereassigned, not null pointer exception.

The final code is as follows.

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) {
    
    
            return root.right;
        } else if (root.right == null) {
    
    
            return root.left;
        }
    }

    TreeNode cur = root;
    TreeNode pre = null;
    while (cur != null) {
    
    
        if (key == cur.val) {
    
    
            // leaf
            if (cur.left == null && cur.right == null) {
    
    
                if (pre.left == cur)
                    pre.left = null;
                if (pre.right == cur)
                    pre.right = null;
            } else if (cur.left == null) {
    
    
                if (pre.left == cur)
                    pre.left = cur.right;
                if (pre.right == cur)
                    pre.right = cur.right;
            } else if (cur.right == null) {
    
    
                if (pre.left == cur)
                    pre.left = cur.left;
                if (pre.right == cur)
                    pre.right = cur.left;
            } else {
    
    
                TreeNode rightTreeMin = cur.right;
                pre = cur;
                while (rightTreeMin.left != null) {
    
    
                    pre = rightTreeMin;
                    rightTreeMin = rightTreeMin.left;
                }
                cur.val = rightTreeMin.val;
                // delete rightTreeMin
                if (pre == cur) {
    
    
                    pre.right = rightTreeMin.right;
                } else {
    
    
                    pre.left = rightTreeMin.right;
                }
            }
            break;
        } else if (key > cur.val) {
    
    
            pre = cur;
            cur = cur.right;
        } else {
    
    
            pre = cur;
            cur = cur.left;
        }
    }
    return root;
}

Guess you like

Origin blog.csdn.net/qq_41512783/article/details/110769270