Given two integer arrays preorder and inorder where preorder is the preorder traversal and inorder is the inorder traversal of the same tree, construct and return the binary tree.
β’ 1 β€ preorder.length β€ 3000β’ All values are uniqueβ’ inorder.length == preorder.length
02
Section Two Β· Approach 1
Linear Search for Root β O(nΒ²)
For each recursive call, scan inorder to find the root's position. This linear search gives O(n) per level β O(nΒ²) total. A HashMap pre-stores positions for O(1) lookup.
03
Section Three Β· Approach 2
Recursive + HashMap β O(n)
Key insight: the first element in preorder is always the root. Find that root's position in inorder β everything left is the left subtree, everything right is the right subtree. Recurse.
π‘ Mental model: Preorder says "who's the boss" (root comes first). Inorder says "who sits left vs right of the boss." Together they uniquely define the tree. The HashMap lets you instantly find where the boss sits in the inorder line.
Algorithm
Step 1: Build a HashMap: inorder value β index.
Step 2: Maintain a preIdx pointer (starts at 0) that advances through preorder.
Step 3: Recursive build(inLeft, inRight):
Create node from preorder[preIdx++].
Find root's position in inorder: mid = map.get(node.val).
node.left = build(inLeft, mid - 1).
node.right = build(mid + 1, inRight).
π― Why preIdx advances globally:
Preorder visits root β left subtree β right subtree.
By incrementing a single pointer, we naturally consume the correct root for each successive recursive call.
The left subtree call consumes all its roots before the right subtree call begins.
04
Section Four Β· Trace
Visual Walkthrough
preorder=[3,9,20,15,7], inorder=[9,3,15,20,7]
05
Section Five Β· Implementation
Code β Java & Python
Java β Recursive + HashMap
import java.util.HashMap;
classSolution {
int preIdx = 0;
HashMap<Integer, Integer> inMap = newHashMap<>();
publicTreeNodebuildTree(int[] preorder, int[] inorder) {
for (int i = 0; i < inorder.length; i++)
inMap.put(inorder[i], i);
return build(preorder, 0, inorder.length - 1);
}
privateTreeNodebuild(int[] preorder, int inLeft, int inRight) {
if (inLeft > inRight) returnnull;
TreeNode root = newTreeNode(preorder[preIdx++]);
int mid = inMap.get(root.val);
root.left = build(preorder, inLeft, mid - 1);
root.right = build(preorder, mid + 1, inRight);
return root;
}
}
Python β Recursive + dict
classSolution:
defbuildTree(self, preorder, inorder):
in_map = {val: i for i, val in enumerate(inorder)}
self.pre_idx = 0defbuild(left, right):
if left > right: returnNone
val = preorder[self.pre_idx]
self.pre_idx += 1
root = TreeNode(val)
mid = in_map[val]
root.left = build(left, mid - 1)
root.right = build(mid + 1, right)
return root
return build(0, len(inorder) - 1)
06
Section Six Β· Analysis
Complexity Analysis
Approach
Time
Space
Linear search for root
O(nΒ²)
O(h)
HashMap β optimal
O(n)
O(n) β map + recursion
07
Section Seven Β· Edge Cases
Edge Cases & Pitfalls
Case
Input
Why It Matters
Single node
[1], [1]
Root only, no children.
Left-skewed
[3,2,1], [1,2,3]
Each node is only a left child.
β Common Mistake: Building the right subtree before the left subtree. Preorder visits left subtree first β so the global preIdx must consume all left-subtree roots before the right subtree's roots. Always call build(left) before build(right).