AlgoMaster Logo

Flatten Binary Tree to Linked List

Last Updated: March 29, 2026

medium
4 min read

Understanding the Problem

We need to rearrange a binary tree so that it becomes a right-skewed "linked list" using the existing TreeNode structure. Every node's left child must be null, and its right child must point to the next node in pre-order sequence. The key word here is "pre-order": root, then left subtree, then right subtree.

The real challenge is doing this restructuring without losing access to subtrees as we rewire pointers. If you naively set node.right = node.left, you lose the original right subtree. That tension between rewiring and preserving access is what makes this problem interesting.

Key Constraints:

  • Number of nodes in range [0, 2000] — With at most 2,000 nodes, any O(n) or even O(n^2) solution runs comfortably. Performance isn't the bottleneck here. The challenge is getting the pointer manipulation right.
  • -100 <= Node.val <= 100 — Node values don't affect the logic. We're restructuring the tree, not computing anything from values.
  • The tree can be empty (0 nodes), so we need to handle the null root case.

Approach 1: Pre-order Traversal with List

Intuition

The most straightforward way to think about this: if we do a pre-order traversal and collect all nodes into a list, we already have them in the correct order. Then we just rewire each node in the list so that its left is null and its right points to the next node.

This is the "just do what the problem says" approach. It's not space-efficient, but it's dead simple and a great starting point in an interview.

Algorithm

  1. If the root is null, return.
  2. Perform a pre-order traversal (root, left, right) and store all nodes in a list.
  3. Iterate through the list. For each node at index i:
    • Set node.left = null.
    • Set node.right = list[i + 1] (or null for the last node).

Example Walkthrough

1Start pre-order traversal: visit root (1)
1visit23456
1/5

Code

This approach works correctly but uses O(n) extra space for the list. What if we could rewire pointers during traversal instead of collecting all nodes first?

Approach 2: Reverse Post-order (Recursive)

Intuition

Here's a clever observation. If we process the tree in reverse pre-order (right subtree, then left subtree, then root), the last node we process is the first node of the flattened list. So we can keep a running pointer called prev that tracks the previously processed node. When we visit the current node, we set current.right = prev and current.left = null, then update prev = current.

Why does this work? In pre-order, the sequence is: root, left subtree, right subtree. If we reverse that, we get: right subtree, left subtree, root. So the very first node we process is the rightmost leaf (last in the flattened list), and the very last node we process is the root (first in the flattened list). By maintaining prev, each node already knows what comes after it.

Algorithm

  1. Initialize a variable prev to null.
  2. Define a recursive function that processes each node:
    • If node is null, return.
    • Recurse on node.right first.
    • Recurse on node.left.
    • Set node.right = prev and node.left = null.
    • Update prev = node.
  3. Call the function on root.

Example Walkthrough

1Start reverse pre-order: go right first. Process node 6 (rightmost leaf). prev=null
123456process
1/6

Code

This approach eliminates the extra list but still uses O(h) stack space from recursion. Can we flatten the tree without any extra space at all?

Approach 3: Morris Traversal (Iterative, O(1) Space)

Intuition

This is the approach the follow-up is hinting at. The core idea comes from Morris traversal, which lets you traverse a tree without recursion or a stack by temporarily modifying the tree structure.

Here's the key insight: for each node, if it has a left subtree, we need to move that entire left subtree to the right. But we can't just overwrite node.right because we'd lose the original right subtree. So before moving anything, we find the rightmost node of the left subtree and connect it to the original right subtree. This way, when we later traverse down the (now right-shifted) left subtree, we'll eventually reach the original right subtree.

Think of it like reorganizing a filing cabinet. Before you move a folder from the left drawer to the right drawer, you first make sure the last item in that folder has a note pointing to whatever was originally in the right drawer. That way nothing gets lost.

Algorithm

  1. Start with current = root.
  2. While current is not null:
    • If current has a left child:

a. Find the rightmost node of the left subtree (call it predecessor).

b. Set predecessor.right = current.right (stitch the right subtree).

c. Set current.right = current.left (move left subtree to the right).

d. Set current.left = null (clear the left pointer).

  • Move to current = current.right.

Example Walkthrough

1current=1: has left child. Find rightmost of left subtree → 4
1current234rightmost56
1/5

Code