Invert Binary Tree
Mirror a binary tree: swap every node's left and right children.
Open on LeetCode ↗Intuition
Writing node.left = invert(node.right) then node.right = invert(node.left) looks fine but is not: the first line overwrites node.left before the second line can read its original value, so the whole left subtree is silently lost. Swap the two child references simultaneously, with a temp variable or tuple assignment, and only then recurse into the (now swapped) children. The invariant is simple: after visiting a node, its left and right pointers must already point at each other's old subtrees before you descend.
Swap each node's children, then recurse into both. Because the swap happens before the recursive calls, the children being inverted are already in their final positions — the order doesn't actually matter here, but stating it keeps the reasoning clean.
Approach
Base case
An empty node has nothing to mirror -- return None immediately.
Swap before recursing
temp = node.left; node.left = node.right; node.right = temp. Do this in one atomic step so neither assignment clobbers data the other still needs.
Recurse into both sides
Call invert on node.left and node.right (which are now swapped) so the mirroring applies at every depth, not just the top.
Solution & live demo
Common pitfalls
Assigning the children sequentially
root.left = root.right root.right = root.left
root.left, root.right = root.right, root.left
The first line overwrites root.left before the second reads it, so both children end up as the original right subtree and the left one is lost. Simultaneous assignment reads both before writing.
Recursing before capturing the swap
self.invertTree(root.left) self.invertTree(root.right) root.left, root.right = root.right, root.left
root.left, root.right = root.right, root.left self.invertTree(root.left)
Both orders happen to work — inverting then swapping is the same as swapping then inverting — but mixing a partial swap with recursion does not. Keeping the swap atomic and first avoids reasoning about it at all.
Forgetting to return the root
self.invertTree(root.left) self.invertTree(root.right)
return root
The mutation is in place, but the signature requires the root back. Returning None implicitly makes the caller think the tree is empty.
Edge cases
Return None right away.
Swap of two Nones is a no-op; returns the same node.
That child moves to the other side; the swap still works since the missing side is just None.
Still fully swapped at every node -- symmetry does not mean invert is a no-op unless every value repeats mirrored.