Construct Binary Tree from Preorder and Inorder Traversal - JS Solution

JS
Editorial

Solution explanation

Solution explanation

Approach

πŸ” Goal

Reconstruct the binary tree from the given preorder and inorder traversals where node values are unique.

🧰 Setup

  • inorderIndexMap β€” a lookup table mapping each value in inorder to its index. It is filled by iterating once over the inorder array and storing each pair (value β†’ index), giving O(1) access later when finding where a root appears in inorder to split it into left and right subtrees β€” avoiding repeated scans.
  • preorderIndex = 0 β€” a pointer tracking the next node to become a root in the construction process. Since preorder lists roots first (Root β†’ Left β†’ Right), this pointer moves forward each time a new subtree is built, ensuring that nodes are created in correct preorder order.

🧠 Key Idea

  • Preorder lists nodes as Root β†’ Left β†’ Right, so the next unused preorder[preorderIndex] is the root for the current subtree.
  • Inorder lists nodes as Left β†’ Root β†’ Right, so finding the root’s position in inorder splits the range into its left and right subtrees.
  • We build with a recursive function buildTreeHelper(left, right) that constructs the subtree spanning inorder[left..right].

πŸͺœ Algorithm (buildTreeHelper)

  1. Base case: if left > right, return null β€” this means there are no elements in this inorder range to form a subtree.
  2. Pick root: rootVal = preorder[preorderIndex++]. Create a new node with this value β€” since preorder lists roots first, this element always becomes the root of the current subtree. Then, advance preorderIndex to point to the next node that will serve as the root in a future recursive call.
  3. Split inorder: rootIdx = inorderIndexMap.get(rootVal). Using this index, we can safely divide the inorder array into two parts β€” all elements to the left of rootIdx belong to the left subtree, and all elements to the right belong to the right subtree:
    • Left subtree: build with buildTreeHelper(left, rootIdx - 1) and attach to root.left.
    • Right subtree: build with buildTreeHelper(rootIdx + 1, right) and attach to root.right.
  4. Return root after both subtrees are attached.

🧩 Intuition β€” Why We Can Safely Split

The guarantee comes directly from what the traversals encode:

  • Preorder (Root β†’ Left β†’ Right): the next unread element is always the root of the current subtree.
  • Inorder (Left β†’ Root β†’ Right): all nodes to the left of the root’s index belong to the left subtree, and all nodes to the right belong to the right subtree.

Thus, after taking the root from preorder and locating it in inorder, the inorder slice [left..rootIdx-1] is exactly the left subtree and [rootIdx+1..right] is exactly the right subtree. This holds recursively, so the reconstruction is unique and correct.

πŸ” Ordering of Recursive Calls

We call buildTreeHelper on the left slice before the right slice to mirror preorder’s Root β†’ Left β†’ Right order. This keeps preorderIndex aligned with what the next root should be.

Time Complexity

O(n), where n is the number of nodes β€” each node is created once, and each inorder index is looked up in O(1) via the map.

Space Complexity

Let n be the number of nodes and h be the tree height. O(n) for building the inorderIndexMap and constructing the output tree, plus O(h) for the recursion stack (worst case: skewed tree β†’ O(n)). Overall O(n).

Visucodize editorial solution titled JS Solution for LeetCode's Construct Binary Tree from Preorder and Inorder Traversal coding problem. Includes code and may include explanation. You can animate the code step by step using the provided input by clicking the run button, or fork it locally to update the code and input for custom visualization. View the original problem at https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal.