Invert Binary Tree
Given the root of a binary tree, produce its mirror image — at every node, the left subtree and the right subtree trade places — and return the root. The values stay where they are relative to their node; only the links move. The tree is modified in place and the same root node is returned. An empty tree (null root) is returned unchanged.
- The number of nodes in the tree is in the range [0, 100]
- -100 <= Node.val <= 100
- Modify the existing nodes in place; do not build a second tree
- Return the root of the modified tree
root = [4,2,7,1,3,6,9][4,7,2,9,6,3,1]root = [2,1,3][2,3,1]root = [1,2,null,3][1,null,2,null,3]root = [][]Mirroring a tree means: hold it up to a mirror and rebuild what you see. A node that sat on the left of its parent now sits on the right, and this has to be true at every level, not just under the root — in the reflection, a deep node's descendants are mirrored too. So the operation is not "swap the root's two children"; it is "swap every node's two children."
That last sentence, read literally, is already the algorithm. But it is worth seeing why one line of swapping is enough, because the same reasoning is what makes almost every tree recursion work.
Look at the root. In the mirrored tree, the entire left subtree has to end up hanging off the right link, and the entire right subtree off the left link. That is a single pointer swap. But the two subtrees also have to be mirrored internally, and here is the point: "mirror this subtree" is the identical problem we started with, only on a smaller tree.
So the job splits cleanly into three pieces:
And the smallest possible case answers itself: an empty tree, null, is already its own mirror, so there is nothing to do and we return. Every recursive call moves strictly one level down toward that case, so the process terminates. Correctness then rides up from the bottom: leaves are trivially mirrored, a node whose two subtrees are correctly mirrored and whose links are swapped is itself correctly mirrored, and so on up to the root.
def invert(node):
if node is None: # empty tree is already its own mirror
return None
node.left, node.right = node.right, node.left # the one real action
invert(node.left) # mirror the subtrees, whichever side they now sit on
invert(node.right)
return nodeYou are not tracing what happens inside those two calls. You assume each one correctly mirrors the subtree it is handed — which is legitimate for exactly the reason above — and you write only the one honest step that belongs to this node.
The traversal question from the previous problem was: when does a node do its work — before its children, or after? Here, unusually, the answer is "either." Swap first and then recurse, and the calls simply receive the subtrees at their new addresses; the left call now handles what used to be the right subtree, mirrors it correctly, and the fact that it is sitting on the other side is irrelevant to it. Recurse first and then swap, and each subtree gets mirrored internally before being moved wholesale; moving an already-correct subtree does not disturb anything inside it.
The reason both work is that the swap at a node and the mirroring inside its subtrees touch disjoint links. The swap rewrites this node's two link fields; the recursive work rewrites link fields strictly deeper down. Two operations that never write the same memory can happen in either order. Hold on to that test — it is the general reason a tree problem is order-free, and it is exactly what fails in problems like Flatten Binary Tree, where the node's own rewiring destroys the very pointer the recursion still needs to find its subtree. There, order is forced.
tmp = node.left; node.left = node.right; node.right = tmp. Writing node.left = node.right first overwrites the only reference to the old left subtree, and that subtree is then unreachable: half the tree quietly disappears and both sides end up as copies of the original right subtree.Each node is visited once and does a constant amount of work — one null check, one swap — so the time is O(N). There is no extra data structure, but the recursion holds one frame per node on the current root-to-node path, so the space is O(H) where H is the height: about log₂N for a balanced tree, and N in the worst case of a single chain. Swapping level by level with a queue (the breadth-first walk introduced in Level Order Traversal) is an equally valid alternative with the same O(N) time and O(width) memory — useful to mention when an interviewer raises deep-recursion concerns.
The habit worth taking away: when a transformation is described as applying "at every node," stop hunting for a loop over levels and instead ask what the single node's job is and whether the rest is the same problem on the two subtrees. Here it was one swap plus two smaller mirrors. That decomposition — one local action, two recursive calls, one base case — is the skeleton behind Same Tree, Symmetric Tree (which is this mirror idea used as a comparison rather than a modification), and Maximum Depth. The only thing that changes across those problems is what the local action is, and whether it must happen before or after the calls.
Invert Binary Tree
Mirroring Strategy
Original Tree
Start at the Root node (4) to begin the Pre-order inversion.
"To invert is to swap. We swap L/R sub-pointers at every level."
Strategy
Recursion ensures every nested subtree is inverted before being attached to its parent.
"[left, right] = [right, left]"
Strategy
Focus on the recursive nature of trees: solve for subtrees and combine results at the root.
"Divide and Conquer: Subproblem → Recurrence → Result"