Given two integer arrays preorder and inorder — the preorder and inorder traversals of the same binary tree, where all values are unique — construct and return the binary tree.
The tree is returned in level-order (breadth-first), using null for missing children.
Input: preorder = [3, 9, 20, 15, 7], inorder = [9, 3, 15, 20, 7]
Output: [3, 9, 20, null, null, 15, 7]
Root 3, left subtree {9}, right subtree rooted at 20 with children 15 and 7.Input: preorder = [-1], inorder = [-1] Output: [-1] A single node.
- 1 <= preorder.length <= 3000 - inorder.length == preorder.length - -3000 <= values <= 3000 - All values are unique - preorder and inorder are traversals of the same tree
Preorder's first element is the root. Find that root in inorder: everything to its left is the left subtree, everything to its right is the right subtree — and the counts tell you how to split preorder too. Recurse. Searching inorder each time is O(n²); a value→index hash map makes each split O(1), giving O(n).
“Are values unique?”
Yes — so a value maps to exactly one inorder position.
“Can the tree be empty?”
Yes — both arrays empty means a null tree.
The first preorder value is the root; I find it in inorder to split into left and right subtrees.
I hash each value to its inorder index so the split is O(1), and consume preorder left-to-right as I recurse.
Worked example — preorder = [3, 9, 20, 15, 7], inorder = [9, 3, 15, 20, 7]
root = 3 (preorder[0]); in inorder, 3 is at index 1
left inorder = [9] -> subtree {9}
right inorder = [15,20,7] -> root 20, split into 15 | 7
result:
3
/ \
9 20
/ \
15 7
The first preorder value is always the current subtree's root; inorder partitions the rest.
Precomputing inorder indices turns each O(n) search into O(1).
Consuming preorder left-to-right (root, then whole left subtree, then right) needs just an incrementing index.
| Slice + search inorder | Hash map + index pointer | |
|---|---|---|
| Idea | Find root in inorder each call, slice arrays | O(1) split via a value->index map |
| Time | O(n^2) | O(n) |
| Space | O(n^2) slices | O(n) |
Both build the same tree; the map version avoids repeated searching and array copies. Full code is in the Approaches selector below.
Key takeaway
Root = preorder[0]; split inorder around it into left/right; recurse. Use a value→inorder-index map + a moving preorder pointer for O(n).
build(lo, hi): # inorder range
if lo > hi: return null
root = preorder[pre++]; m = index[root]
node.left = build(lo, m-1)
node.right = build(m+1, hi)