Construct Binary Tree from Preorder and Inorder Traversal

MediumBinary Tree · Divide & Conquer🧩 Tree DFSLeetCode #105 ↗Updated

Problem

You are given two arrays, preorder and inorder, which are the pre-order and in-order traversals of the same binary tree with distinct values. Rebuild that tree and return its root.
Inputpre=[3,9,20,15,7], in=[9,3,15,20,7]Output[3,9,20,null,null,15,7]
Inputpre=[-1], in=[-1]Output[-1]

1 ≤ n ≤ 3000  ·  -3000 ≤ val ≤ 3000  ·  all values distinct  ·  both arrays describe the same tree

Try it yourself

Java
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
preorder[0] is the root; its position k in inorder splits the rest into left subtree (k values) and right subtree. Recurse on the two halves — the only cost to optimise is finding k.
PatternTree DFS

Instinct If the answer for a node can be built from the answers of its left and right subtrees, write one recursive function and trust it on the children.

Memory hack Ask the kids, then decide - each child reports up, the parent combines, and a global variable keeps the best "bend" seen so far.

Open the Tree DFS guide →

Approaches

Brute ForceRecursion on Copied Subarrays

Time O(n2)Space O(n2)

Take the root from preorder[0], scan inorder for it to get the left size k, then slice both arrays into new left/right arrays and recurse. On a skewed tree each level copies and scans almost n values, and all those copies are alive on the recursion path.

Java
public TreeNode buildTree(int[] preorder, int[] inorder) {
    int n = preorder.length;
    if (n == 0) return null;
    TreeNode root = new TreeNode(preorder[0]);
    int k = 0;
    while (inorder[k] != root.val) k++; // k = size of left subtree
    root.left = buildTree(Arrays.copyOfRange(preorder, 1, k + 1),
                          Arrays.copyOfRange(inorder, 0, k));
    root.right = buildTree(Arrays.copyOfRange(preorder, k + 1, n),
                           Arrays.copyOfRange(inorder, k + 1, n));
    return root;
}

Mirrors the definition exactly, but copying + scanning is quadratic.

At a glance

LevelApproachTimeSpace
Brute ForceRecursion on Copied SubarraysO(n2)O(n2)
BetterIndex Ranges + Linear SearchO(n2)O(h)
OptimalHash Map of Inorder Indices + Preorder PointerO(n)O(n)
Common pitfalls
  • Building the right subtree before the left — the preorder pointer then picks wrong roots.
  • Off-by-one in the right subtree's preorder start: it is preStart + leftSize + 1.
  • Relying on distinct values silently — with duplicates the split is ambiguous.
Interview tips
  • Draw one example and mark the root in both arrays to show the split.
  • Mention why preorder alone (or inorder alone) can't define a tree uniquely.
  • Note recursion depth = height: up to 3000 on a skewed tree.
Pattern
Traversal-based reconstruction → root from pre/postorder, split sizes from inorder, recurse.
My notes saved in this browser