LeetCode Β· #105

Construct Binary Tree from Preorder and Inorder Solution

Given preorder and inorder traversals of a tree with unique values, construct and return the binary tree.

01
Section One Β· Problem

Problem Statement

🏷️

Difficulty

Medium

πŸ”—

LeetCode

Problem #105

πŸ—οΈ

Pattern

Construction β€” preorder root + inorder split

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.

Example
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] Output: 3 / \ 9 20 / \ 15 7
Constraints
β€’ 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]
PREORDER (root first) 3 9 20 15 7 ↑ root INORDER (left | root | right) 9 3 15 20 7 ←left root rightβ†’ RESULT 3 9 20 15 7 RECURSIVE BUILD TRACE β‘  preIdx=0 β†’ root=3 In inorder: pos=1. Left=[9], Right=[15,20,7] Create node(3), recurse left then right β‘‘ preIdx=1 β†’ root=9 In inorder: pos=0. Left=[], Right=[] β†’ leaf β‘’ preIdx=2 β†’ root=20 In inorder: pos=3. Left=[15], Right=[7] β‘£ preIdx=3 β†’ root=15 Leaf. β‘€ preIdx=4 β†’ root=7. Leaf. Done! Tree: 3β†’[9, 20β†’[15, 7]] βœ“
05
Section Five Β· Implementation

Code β€” Java & Python

Java β€” Recursive + HashMap
import java.util.HashMap; class Solution { int preIdx = 0; HashMap<Integer, Integer> inMap = new HashMap<>(); public TreeNode buildTree(int[] preorder, int[] inorder) { for (int i = 0; i < inorder.length; i++) inMap.put(inorder[i], i); return build(preorder, 0, inorder.length - 1); } private TreeNode build(int[] preorder, int inLeft, int inRight) { if (inLeft > inRight) return null; TreeNode root = new TreeNode(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
class Solution: def buildTree(self, preorder, inorder): in_map = {val: i for i, val in enumerate(inorder)} self.pre_idx = 0 def build(left, right): if left > right: return None 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

ApproachTimeSpace
Linear search for rootO(nΒ²)O(h)
HashMap ← optimalO(n)O(n) β€” map + recursion
07
Section Seven Β· Edge Cases

Edge Cases & Pitfalls

CaseInputWhy 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).

← Back to Trees problems