Flatten Binary Tree to Linked List
Rearrange the tree in place into a chain that leans entirely to the right: every node's left pointer must end up null, and its right pointer must point to the next node in the tree's original pre-order sequence. The last node's right is null. You must reuse the existing nodes and rewire their pointers rather than allocating new ones, and the same root object is the head of the resulting chain. An empty tree stays empty.
- The number of nodes in the tree is in the range [0, 2000]
- -100 <= Node.val <= 100
- The transformation must be in place — no new nodes
- Every left pointer must be null when you finish
root = [1,2,5,3,4,null,6]1 → 2 → 3 → 4 → 5 → 6, all via right pointers, all left pointers nullroot = [1,null,2,null,3]1 → 2 → 3root = [1,2,null,3]1 → 2 → 3root = [][]Flatten means rewire the tree, in place, into one right-leaning chain. The order along the chain is the tree's pre-order: node, then its whole left subtree, then its whole right subtree. Every left pointer ends up null.
1
/ \
7 9 pre-order walk: 1 7 3 4 9 2
/ \ \
3 4 2
becomes: 1 -> 7 -> 3 -> 4 -> 9 -> 2 (all along right pointers)Tempting first move: at each node, swing the left subtree over to the right pointer.
1 node.right = node.left
/ \ node.left = None
7 9But node.right = node.left overwrites the only link to 9 and everything beneath it — that whole subtree just vanishes. A node's own rewrite clobbers a pointer the recursion still needs. Lesson: never overwrite a link until you're done reading what it points to.
The crash happened because we linked a node forward before we were done with its old pointers. So flip it around: build the chain starting from its last node, working backward to the root.
Here's why that fixes everything. To give a node its new right pointer, the node that comes after it in the chain must already exist — then we just point at it. If we always handle nodes in reverse chain order, that successor is already built and parked in a variable tail. Every write is "point at something already finished," so we never clobber a pointer we still need.
suppose the tail end is already linked: 9 -> 2 (tail = 9)
now handle 4: point 4's right at tail -> 4 -> 9 -> 2 (tail = 4)
now handle 3: -> 3 -> 4 -> 9 -> 2 (tail = 3)And reverse chain order is easy to produce, because the chain order is pre-order (node, left, right). Reverse it and you get right, left, node: walk the right subtree first, then the left, do the node last. Each node then just points right at tail, nulls its left, and becomes the new tail.
visit order (reverse pre-order): 2 9 4 3 7 1
2 tail = 2
9 -> 2 tail = 9
4 -> 9 -> 2 tail = 4
3 -> 4 -> 9 -> 2 tail = 3
7 -> 3 -> 4 -> 9 -> 2 tail = 7
1 -> 7 -> 3 -> 4 -> 9 -> 2 donetail = None
def flatten(node):
nonlocal tail
if node is None:
return
flatten(node.right) # far end of the chain, built first
flatten(node.left)
node.right = tail # link forward to the already-built part
node.left = None
tail = node # this node is now the frontThe whole trick is one ordering: flatten(node.right) reads the right pointer on the first line, while it's still intact; node.right = tail writes it only after both subtrees are fully handled and don't need their old links. Move that write above the calls and you're back to the self-destructing version.
O(N) time — each node written once — and O(H) stack. (An O(1)-space variant threads the tree iteratively: for each node with a left child, splice its right subtree onto the left subtree's rightmost node, move the left subtree over to the right, and step right.)
In-Place Flattening
Reverse Pre-Order Stitching
"To flatten without extra space, process from tail to head."
Strategy
A reverse pre-order (Right → Left → Root) visits nodes in the exact opposite order they appear in the flattened list. This allows us to point `node.right` to the `prev` node easily.
"Right → Left → Root"