Recover BST (Two Nodes Swapped)
WHAT IT SAYS
Exactly two nodes of a BST had their values swapped by mistake. Restore the tree without changing its structure.
WHAT IT'S REALLY ASKING
"A healthy BST's inorder stream climbs steadily upward. Swap two values and the stream stumbles — it DESCENDS somewhere it never should. One stumble if the culprits were inorder-neighbours, two stumbles if they were strangers. The corruption doesn't hide: it announces itself as the exact places the sorted order breaks, and the fix is to swap back what the stumbles point at."
Flatten, sort, and rewrite every node
O(n log n) time, O(n) space, two full passes plus a sortInorder-collect all values into an array, sort the array, then run inorder again writing the sorted values back into the nodes in order.
WHERE THE WORK IS WASTED — The sort is a sledgehammer aimed at two loose screws: the collected array is ALREADY sorted except for exactly two positions, and comparison sorting re-derives the order of n-2 elements whose order was never in doubt. The O(n) buffer stores an almost-sorted sequence whose defects a single trailing comparison could have flagged in flight. And rewriting every node's value — even the untouched ones — treats a surgical two-node correction as a full transplant. The problem statement said 'exactly two'; this solution never reads that sentence.
One swap makes at most two descents in the stream.
Let the healthy inorder sequence be strictly increasing, and suppose values at sorted positions i and j (i < j) got exchanged: the larger value now sits early, the smaller sits late. Scan the corrupted inorder stream with one question — 'did this element fail to exceed its predecessor?' — and case-split on adjacency. If i and j are inorder-adjacent, the stream reads ...a, Y, X, b... where X < Y: exactly ONE descent, at the Y→X boundary, and both culprits are its two endpoints. If they are not adjacent, the stream reads ...Y...X... with correct values between: the FIRST descent happens where Y (too big, too early) exceeds its successor — culprit one is the descent's LEFT element; the SECOND descent happens where X (too small, too late) fails to exceed its predecessor — culprit two is that descent's RIGHT element. Why can't a single swap make three descents? Each misplaced value disturbs the order only at its own borders: Y disturbs the border after it, X the border before it — two borders maximum, and they coincide in the adjacent case. So the detection rule is mechanical: walk inorder with a trailing prev; at the first violation record first = prev and second = current; at any second violation overwrite second = current. After the walk, swap first.val with second.val — the rule covers both cases uniformly because in the adjacent case the second violation simply never arrives, leaving second correctly pointing at the first descent's right element. One pass, one prev pointer, two node references. The 'exactly two swapped' promise is what licenses stopping the diagnosis at two descents — this is Validate BST's monotone-stream check, upgraded from detecting corruption to LOCATING it. The O(1)-space flourish: the walk above still costs O(h) stack. Morris inorder — threading each left subtree's rightmost node back to its root as a temporary return address — delivers the same inorder stream with zero stack, and the prev-comparison rides on top unchanged. The two techniques compose because Morris changed HOW the stream is produced, not WHAT it contains.
Inorder with a trailing prev, record two violations, swap values
O(n) time, O(h) space — or genuinely O(1) with Morris as the stream engineWalk inorder (recursive, iterative, or Morris) carrying prev. On each visit: if prev exists and prev.val ≥ current.val, then first = prev if unset, and second = current always. After the walk, exchange first.val and second.val. Structure untouched; values restored.
Violations Are Coordinates
YOU'LL SEE IT AGAIN WHEN
- A bounded corruption ('exactly two swapped', 'one element modified') of a structure whose invariant linearises to a monotone stream.
- Each misplaced element disturbs only its own borders in the stream, so k corruptions yield at most 2k violations with predictable geometry.
- The repair is surgical — swap or rewrite only what violations name — making full re-sorting provably excessive.