Delete Node in a BST
WHAT IT SAYS
Remove the node holding a given key from a BST, keeping the tree a valid BST.
WHAT IT'S REALLY ASKING
"Zero children: unhook it. One child: splice the child through. Two children is the case that looks hard — until you ask who could sit in this seat without breaking order. Exactly two candidates exist: the largest value on the left, or the smallest on the right. And here is the gift: each of those candidates has AT MOST ONE child, so evicting it from its old position is one of the easy cases. The hard case doesn't get solved — it gets demoted."
Rebuild the tree without the key
O(n) time minimum, O(n) space, and the original structure is discardedTraverse the whole tree collecting every value except the target, then construct a fresh BST from the collection — insert one by one, or sort and build.
WHERE THE WORK IS WASTED — Deletion is a LOCAL event — one node leaves, and the ordering relations among all other pairs are untouched — but rebuilding treats it as global catastrophe, re-deriving n-1 nodes' worth of structure that was never in question. Worse than the time is what gets destroyed: the tree's existing shape (and any balance it had) is thrown away, subtree references held elsewhere dangle, and an O(h) pointer adjustment has been inflated into an O(n) reconstruction. The blast radius of removing one node is that node's immediate neighbourhood; everything beyond it is collateral damage you invented.
The successor never has a left child.
Walk the three cases in order of what they teach. No children: the node's absence needs no repair — null out the parent's pointer. One child: the node was a waypoint on a single path; splice the child into its place, and every ordering relation is preserved because the child's entire subtree already lived on the correct side of every ancestor. Both cases are pure pointer moves, O(1) beyond finding the node. Two children is where the structure fights back: neither child can simply take the seat, because promoting the left child orphans the right subtree and vice versa. So ask the question that dissolves it: which VALUE could occupy this position and keep every comparison in the tree correct? The seat's constraints are 'greater than everything in the left subtree, less than everything in the right'. Only two values in the tree satisfy that: the maximum of the left subtree (the inorder predecessor) or the minimum of the right subtree (the inorder successor) — the values immediately adjacent to the departing key in sorted order. Adjacency is exactly why they fit: nothing in the tree lies between them and the deleted key, so no comparison can distinguish them from it. Now the fact that turns a swap into a full algorithm: the minimum of the right subtree is found by walking left from the right child until left turns run out — so by construction IT HAS NO LEFT CHILD. Symmetrically the left subtree's maximum has no right child. The candidate is always a zero-or-one-child node. So the procedure is: copy the successor's value into the seat, then delete the successor from where it was — and THAT deletion is guaranteed to hit one of the two easy cases. The two-child case never recurses into itself; it fires exactly once and hands off. This is reduction, not recursion: the hard case's entire job is to transform itself into an easy case somewhere deeper.
Search, then case-split, with the two-child case delegating
O(h) time — one descent to find, at most one more descent to the successor — O(h) recursion or O(1) iterativeRecursively descend by comparison until the key matches. Zero or one child: return the other child (possibly null) to the parent's pointer — the reassignment idiom handles both at once. Two children: find the right subtree's minimum, copy its value into the current node, then recursively delete that value from the right subtree, knowing it lands in an easy case.
Demote the Hard Case
YOU'LL SEE IT AGAIN WHEN
- The operation splits into cases by local structure, and all but one case are trivial pointer moves.
- The hard case has a canonical substitute element — the inorder-adjacent value — whose own removal provably lands in a trivial case.
- The substitute is located by a degenerate walk (all-left or all-right), which is what guarantees its child count is deficient.