Flatten Binary Tree
Flatten Binary Tree
Category
Binary Trees
Difficulty
Hard
Problem Statement
Given a binary tree, flatten it into a doubly linked list in place. The linked list should follow the in-order traversal of the tree. The left pointer of each node should point to the previous node in the list, and the right pointer should point to the next node. The function should return the head (leftmost node) of the resulting linked list.
Intuition
An in-order traversal of a binary tree visits nodes in left-root-right order. To flatten the tree into a doubly linked list following this order, we can recursively flatten the left and right subtrees first, then connect the current node between the end of the left list and the beginning of the right list. This is a divide-and-conquer approach that works bottom-up.
Approach
- Define a recursive helper that returns both the head and tail of the flattened linked list for a given subtree.
- Base case: if the node is null, return (null, null).
- Recursively flatten the left subtree, obtaining
leftHeadandleftTail. - Recursively flatten the right subtree, obtaining
rightHeadandrightTail. - Connect
leftTail.rightto the current node, andcurrentNode.lefttoleftTail(if left subtree exists). - Connect
currentNode.righttorightHead, andrightHead.leftto the current node (if right subtree exists). - The head of the combined list is
leftHead(or the current node if no left subtree). - The tail of the combined list is
rightTail(or the current node if no right subtree). - Return the head and tail.
Pseudocode
function flattenBinaryTree(root):
head, _ = flattenTree(root)
return head
function flattenTree(node):
if node is null:
return (null, null)
leftHead, leftTail = flattenTree(node.left)
rightHead, rightTail = flattenTree(node.right)
if leftTail is not null:
leftTail.right = node
node.left = leftTail
if rightHead is not null:
node.right = rightHead
rightHead.left = node
overallHead = leftHead if leftHead is not null else node
overallTail = rightTail if rightTail is not null else node
return (overallHead, overallTail)
Time & Space Complexity
- Time: O(n) where n is the number of nodes. Each node is visited exactly once.
- Space: O(h) where h is the height of the tree, due to the recursion stack. O(log n) for balanced trees, O(n) for skewed trees.
Key Insights
- Returning both head and tail from recursion avoids the need to traverse lists to find endpoints, keeping the algorithm O(n).
- The tree is modified in place — no new nodes are created.
- In-order traversal order is maintained because we connect: left subtree list -> current node -> right subtree list.
- This is a clean example of divide-and-conquer on trees.
- An alternative iterative approach can use a stack-based in-order traversal and link nodes as they are visited.
Edge Cases
- The tree is empty (null root) — return null.
- The tree has only one node — return that node with both left and right set to null.
- A completely left-skewed tree — already almost a linked list going left; needs pointer rewiring.
- A completely right-skewed tree — similar but in the other direction.
- The tree has only left children or only right children — the result is identical to the original structure with minor pointer adjustments.