Construct Binary Tree from Preorder and Inorder Traversal

Mediumtreearraydivide-and-conquerrecursion
Category: Trees
Companies that ask this question:
AmazonMicrosoftFacebookGoogleBloomberg

Approach

Construct Binary Tree from Preorder and Inorder Traversal

Problem Statement

Given two integer arrays preorder and inorder where:

  • preorder is the preorder traversal of a binary tree
  • inorder is the inorder traversal of the same tree

Construct and return the binary tree.

Examples

Example 1

Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]

Tree:
      3
     / \
    9  20
      /  \
     15   7

Example 2

Input: preorder = [-1], inorder = [-1]
Output: [-1]

Intuition

Key Observations:

  1. Preorder: root → left → right (first element is always root)
  2. Inorder: left → root → right (root splits left and right subtrees)

Algorithm:

  1. First element of preorder is the root
  2. Find root in inorder → this splits inorder into left and right subtrees
  3. Elements to left of root in inorder = left subtree
  4. Elements to right of root in inorder = right subtree
  5. Recursively build left and right subtrees

Example:

preorder = [3, 9, 20, 15, 7]
inorder  = [9, 3, 15, 20, 7]

Step 1: Root = 3 (first in preorder)
Step 2: Find 3 in inorder → splits at index 1
        left_inorder = [9]
        right_inorder = [15, 20, 7]
Step 3: Split preorder accordingly:
        left_preorder = [9]      (next 1 element)
        right_preorder = [20, 15, 7]  (remaining)
Step 4: Recursively build subtrees

Pattern Recognition

This is a Divide and Conquer + Tree Construction problem:

  • Use preorder to identify roots
  • Use inorder to partition subtrees
  • Recursive structure

Approach

Recursive with Index Map

  1. Preprocess: Create hashmap of value → index in inorder (O(1) lookup)

  2. Recursive Function: build(pre_start, pre_end, in_start, in_end)

    • Base case: if start > end, return null
    • Root = preorder[pre_start]
    • Find root_index in inorder using hashmap
    • Calculate left_subtree_size = root_index - in_start
    • Build left subtree with appropriate ranges
    • Build right subtree with appropriate ranges
    • Return root
  3. Initial Call: build(0, n-1, 0, n-1)

Time Optimization: HashMap for O(1) lookup instead of O(n) search.

Edge Cases

  • Single node
  • Skewed tree (all left or all right)
  • Duplicate values (problem states values are unique)
  • Empty arrays

Complexity Analysis

  • Time: O(n) where n = number of nodes

    • Build hashmap: O(n)
    • Visit each node once: O(n)
    • O(1) lookup per node with hashmap
  • Space: O(n)

    • Hashmap: O(n)
    • Recursion stack: O(h) = O(log n) to O(n)
    • Total: O(n)

Solution

java
1import java.util.HashMap;
2import java.util.Map;
3
4class TreeNode {
5    int val;
6    TreeNode left;
7    TreeNode right;
8    TreeNode() {}
9    TreeNode(int val) { this.val = val; }
10    TreeNode(int val, TreeNode left, TreeNode right) {
11        this.val = val;
12        this.left = left;
13        this.right = right;
14    }
15}
16
17class Solution {
18    private int preIdx = 0;
19    private Map<Integer, Integer> inorderMap;
20
21    public TreeNode buildTree(int[] preorder, int[] inorder) {
22        // Create hashmap for O(1) lookup of root index in inorder
23        inorderMap = new HashMap<>();
24        for (int i = 0; i < inorder.length; i++) {
25            inorderMap.put(inorder[i], i);
26        }
27
28        return build(preorder, 0, inorder.length - 1);
29    }
30
31    private TreeNode build(int[] preorder, int inStart, int inEnd) {
32        if (inStart > inEnd) {
33            return null;
34        }
35
36        // Root is current element in preorder
37        int rootVal = preorder[preIdx++];
38        TreeNode root = new TreeNode(rootVal);
39
40        // Find root in inorder to split left/right subtrees
41        int rootIdx = inorderMap.get(rootVal);
42
43        // Build left subtree (before root in inorder)
44        root.left = build(preorder, inStart, rootIdx - 1);
45
46        // Build right subtree (after root in inorder)
47        root.right = build(preorder, rootIdx + 1, inEnd);
48
49        return root;
50    }
51}
52
Loading visualizer...