Trees · Binary Tree Fundamentals

Binary Tree Reconstruction

Rebuilding a binary tree from two of its traversal orders by using preorder (or postorder) to pick off the current root value one at a time, and inorder to find where that root's left subtree ends and its right subtree begins - repeated recursively over shrinking index ranges.

  • 7 min read
  • 10 practice questions
  • 2 graded problems
On this page
  1. Description
  2. The approach (from preorder + inorder)
  3. A second flavor: from inorder + postorder
  4. Where you'll see it
  5. Which tool for which job?
  6. Common mistakes
  7. Check yourself
  8. Key takeaways
  9. Quick revise
  10. Practice

Description

Reconstruction rebuilds a binary tree from two of its traversals. Preorder (or postorder) says which node is the root of each subtree. Inorder says where that root splits its subtree into left and right. Walk one sequence with a cursor, find each root's position in the other with a hash map, and recurse on the two sides: O(n) for the whole tree.

We'll go from simple to more technical:

  1. The pattern: preorder + inorder, a shared cursor and an index map.
  2. A second flavor: inorder + postorder, walking the cursor backwards.
  3. Where rebuilding a structure from linear views happens.
  4. Why the build order matters, and when two traversals still aren't enough.

The approach (from preorder + inorder)

One traversal alone can't rebuild a tree, because it doesn't show where one subtree ends and the next begins. Two together can. Preorder lists every root before its subtrees, so the next unused preorder value is always the root of the subtree you're building. Inorder puts every root between its left and right subtrees, so finding the root in inorder splits the remaining values into a left part and a right part.

Rebuilding from preorder 6, 2, 1, 4, 9 and inorder 1, 2, 4, 6, 9:

Next root from preorderIts place in inorderLeft partRight part
6index 31 2 49
2index 114
1index 0(none)(none)
4index 2(none)(none)
9index 4(none)(none)

6

2

9

1

4

6

2

9

1

4

Java

Map<Integer, Integer> inorderIndex; // value -> index, built once up front
int preIdx = 0;

TreeNode build(int[] preorder, int inStart, int inEnd) {
    if (inStart > inEnd) return null;
    int rootVal = preorder[preIdx++];               // next unused preorder value IS the current root
    TreeNode root = new TreeNode(rootVal);
    int mid = inorderIndex.get(rootVal);              // where the root splits inorder into left/right
    root.left  = build(preorder, inStart, mid - 1);   // must build left before right - preIdx is shared, sequential state
    root.right = build(preorder, mid + 1, inEnd);
    return root;
}

Python

def build_tree(preorder: list[int], inorder: list[int]) -> TreeNode | None:
    inorder_index = {v: i for i, v in enumerate(inorder)}   # value -> index, built once up front
    pre = iter(preorder)                                    # one shared cursor into preorder

    def build(in_start: int, in_end: int) -> TreeNode | None:
        if in_start > in_end:
            return None
        root = TreeNode(next(pre))              # next unused preorder value IS the current root
        mid = inorder_index[root.val]           # where the root splits inorder into left/right
        root.left = build(in_start, mid - 1)    # must build left before right - the cursor is shared
        root.right = build(mid + 1, in_end)
        return root

    return build(0, len(inorder) - 1)

Two details matter. The map from value to inorder index makes each split an O(1) lookup, which keeps the whole build O(n). And the left subtree must be built before the right one. The preorder cursor is shared, and preorder lists the whole left subtree before the right one.

A second flavor: from inorder + postorder

Postorder lists each root last, after its left and right subtrees. So read postorder from the end, backwards. The tree above has postorder 1, 4, 2, 9, 6, and reading it backwards gives 6, 9, 2, 4, 1. Reading backwards, the right subtree's values come before the left's, so build the right subtree first:

Java

int postIdx = postorder.length - 1;   // starts at the END, walks backward

TreeNode build(int[] postorder, int inStart, int inEnd) {
    if (inStart > inEnd) return null;
    int rootVal = postorder[postIdx--];               // next unused value from the BACK is the current root
    TreeNode root = new TreeNode(rootVal);
    int mid = inorderIndex.get(rootVal);
    root.right = build(postorder, mid + 1, inEnd);     // build RIGHT before LEFT - the cursor is walking backward
    root.left  = build(postorder, inStart, mid - 1);
    return root;
}

Python

def build_tree(inorder: list[int], postorder: list[int]) -> TreeNode | None:
    inorder_index = {v: i for i, v in enumerate(inorder)}
    post = reversed(postorder)                  # the cursor starts at the END and walks backward

    def build(in_start: int, in_end: int) -> TreeNode | None:
        if in_start > in_end:
            return None
        root = TreeNode(next(post))             # next unused value from the BACK is the current root
        mid = inorder_index[root.val]
        root.right = build(mid + 1, in_end)     # build RIGHT before LEFT - the cursor is walking backward
        root.left = build(in_start, mid - 1)
        return root

    return build(0, len(inorder) - 1)

It's the preorder version mirrored: the cursor runs the other way, so the build order flips too.

Where you'll see it

In real systems you'd usually save a tree with null markers (see Serialize and Deserialize), which needs only one traversal. Rebuilding from two traversals is mainly an interview classic. It's a good test of understanding what each traversal order actually tells you.

Which tool for which job?

You needUse
Tree from preorder + inordercursor forward over preorder; build left, then right
Tree from inorder + postordercursor backward over postorder; build right, then left
Fast root lookups in inordera value → index map, built once
Very deep treesthe iterative stack construction
Tree from preorder + postorderonly unique for full binary trees
Exact round trips in your own codeserialize with null markers instead

Common mistakes

MistakeWhat happensDo this instead
Building right before left from preordersubtrees get each other's valuesleft first - preorder lists it first
Reading postorder from the frontthe wrong rootsstart at the end; build right first
Scanning inorder for each rootO(n^2) on skewed treesa value → index map
Duplicate valuesthe map can't tell nodes apart; the tree is ambiguousrequire distinct values, or use null markers
Recursing on a 100,000-deep treestack overflowthe iterative construction

Check yourself

Try to answer before opening each one - recalling beats re-reading.

1. Building from preorder and inorder, a solution builds the right subtree first. What goes wrong?

Show answer

The preorder cursor is shared, and preorder lists the root, then the whole left subtree, then the right one. Building right first makes the right side take values that belong to the left side. From there on, the tree is built from the wrong values.

2. With inorder and postorder, why start at the end of postorder, and why build the right subtree first?

Show answer

Postorder lists a subtree's root last, so the root is at the end. Reading backwards, the values just before a root belong to its right subtree. So the right subtree has to be built first to take exactly those values.

3. Why does the value-to-index map change the complexity, not just the speed?

Show answer

Every one of the n calls needs its root's position in inorder. Scanning for it costs O(n) each time, O(n^2) in total. The map makes each lookup O(1), so the whole build is O(n).

Key takeaways

  • Preorder or postorder gives each subtree's root. Inorder splits that subtree into left and right.
  • With preorder, read forwards and build left before right.
  • With postorder, read backwards and build right before left.
  • A value-to-index map keeps the build O(n).
  • Both bugs are the same mistake: building the subtrees in an order that doesn't match the cursor's direction.

Quick revise

The whole skill on one page, for the night before an interview.

Everything from the lesson and the deep dive on one page. Skim it before practice or an interview, and open the full lesson for anything that doesn't ring a bell.

Pick the tool

You needUse
Preorder + inorderforward cursor, left then right
Inorder + postorderbackward cursor, right then left
Fast splitsvalue → index map
Deep treesiterative construction
Your own formatnull markers

Snippets worth knowing by heart

Java

int pre = 0;
Map<Integer, Integer> at = new HashMap<>();          // inorder value -> index, built once
TreeNode build(int[] preorder, int lo, int hi) {
    if (lo > hi) return null;
    TreeNode root = new TreeNode(preorder[pre++]);
    int mid = at.get(root.val);
    root.left = build(preorder, lo, mid - 1);         // left first: preorder lists it first
    root.right = build(preorder, mid + 1, hi);
    return root;
}

Python

def build_from_post(inorder, postorder):
    at = {v: i for i, v in enumerate(inorder)}
    post = len(postorder) - 1
    def go(lo, hi):
        nonlocal post
        if lo > hi:
            return None
        root = TreeNode(postorder[post]); post -= 1    # roots from the end
        mid = at[root.val]
        root.right = go(mid + 1, hi)                   # right first, going backwards
        root.left = go(lo, mid - 1)
        return root
    return go(0, len(inorder) - 1)

The traps

  • Right before left from preorder: subtrees swap values. Build left first, because preorder lists it first.
  • Postorder from the front: you pick the wrong roots. Start at the end and build right first.
  • Linear scans for roots: searching inorder each time is O(n^2) on skewed trees. Use a value-to-index map.
  • Duplicate values: the map can't tell nodes apart, so the tree is ambiguous. Require distinct values or null markers.
  • Deep recursion: a 100,000-deep tree overflows the stack. Build it iteratively.

Staff-level points, one line each

  • Duplicates: two different trees shared preorder and inorder.
  • Preorder + postorder: [1, 2] / [2, 1] fits a left or a right child - only full trees are unique.
  • Scans: 2,000 comparisons on a right chain, 2,001,000 on a left chain; a map: 2,000.
  • Recursive rebuild of a 200,000-node chain overflowed; the iterative stack version didn't.

Say it in an interview

  • "Preorder gives me each root; inorder tells me how many nodes go left."
  • "A hash map from value to inorder index makes each split O(1)."
  • "For postorder I read from the end and build the right subtree first."
  • "This needs distinct values."

Practice

This skill comes with 10 multiple-choice questions that tell you which misconception a wrong answer reveals and 2 graded problems. Your answers are graded and your mastery is tracked, so you'll know when the skill holds up. Running code and saving progress need a free account.

Practice Binary Tree Reconstruction free

Construct Binary Tree from Preorder and Inorder Traversal

MediumProCoding problemJava · Python

Given a tree's preorder and inorder traversals (all node values distinct), reconstruct and return the tree.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Construct Binary Tree from Inorder and Postorder Traversal

MediumProCoding problemJava · Python

Given a tree's inorder and postorder traversals (all node values distinct), reconstruct and return the tree.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Practice Binary Tree Reconstruction free

No card needed. Lessons, practice questions and easy problems are free forever.

Free plan, no card · 7-day Pro trial · Cancel anytime