Delete node in a binary search tree

problem [https://leetcode.com/problems/delete-node-in-a-bst/ 450. Delete Node in a BST].

Problem description
Given a root node reference of a BST and a key, delete the node with the given key in the BST. Return the root node reference (possibly updated) of the BST.

Basically, the deletion can be divided into two stages:
 * 1) Search for a node to remove.
 * 2) If the node is found, delete the node.


 * Follow up
 * Can you solve it with time complexity ?


 * Example 1
 * Input: root = [5,3,6,2,4,null,7], key = 3
 * Output: [5,4,6,2,null,null,7]
 * Explanation: Given key to delete is 3. So we find the node with value 3 and delete it.
 * One valid answer is [5,4,6,2,null,null,7], shown in the above BST.
 * Please notice that another valid answer is [5,2,6,null,4,null,7] and it's also accepted. Delete node in a binary search tree - supplement.jpeg


 * Example 2
 * Input: root = [5,3,6,2,4,null,7], key = 0
 * Output: [5,3,6,2,4,null,7]
 * Explanation: The tree does not contain a node with value = 0.


 * Example 3
 * Input: root = [], key = 0
 * Output: []


 * Constraints
 * The number of nodes in the tree is in the range.
 * Each node has a unique value.
 * is a valid binary search tree.
 * is a valid binary search tree.

Analysis
We can first use the method of Search in a binary search tree to locate the node to be deleted. This can be done recursively, and at each level of recursion we can keep track of whether we have stepped into the left subtree or the right subtree.

If we did not find the node to delete, we do nothing and just return root.

Otherwise, if we have found the node to delete, there are several cases analyze:


 * Case 1 : The node to be deleted has no children.
 * Delete from binary search tree 1.svg
 * For the deleted node, We just need to change the left child / right child of its parent (if exists) to.


 * Case 2 : The node to be deleted has only one child.
 * Delete from binary search tree 2.svg
 * For the deleted node, We just need to change the left child / right child of its parent (if exists) to the only child of this node.


 * Case 3 : The node to be deleted has both children.
 * This is the most complicated case. We must proceed carefully to figure out how the nodes are rearranged.
 * Let node D be the node to be deleted. One method is to make use of the right subtree of node D (subtree A) to take over node D's position. The steps are as follows:
 * Find the minimum node of subtree A. Let this be node M.
 * For node M, keep a record of its right subtree (subtree B).
 * Now for subtree B, one of the two possible rearrangements will happen:
 * If the root of subtree A has no left child, then node M must be the right child of node D. We just need to set the left subtree of node D as the left child of subtree A.
 * If the root of subtree A has a left child, then we need to do the following:
 * Pop out node M from subtree A.
 * Let the parent of node M take over subtree B (i.e. set subtree B as the left child of node M's parent).
 * Now for node M:
 * Set its left child to the left child of node D.
 * Set its right child to the rearranged subtree A.
 * After deleting node D, we can traverse back from the recursion, and return the root.
 * Illustration
 * Delete from binary search tree 3.svg

Time complexity

 * The time complexity to search for the node to delete + search for the minimum element in its right subtree take is O(height of tree).
 * After finding these two nodes, rearranging them takes O(1) time.

So total time complexity is O(height of tree).

Space complexity

 * Stack
 * The recursion to find the node to delete has O(height of tree) complexity on stack.


 * Heap
 * Since we did not allocate any new objects, the space complexity on heap is O(1).

So our total space complexity is O(height of tree).