Construct Binary Tree from Preorder and Inorder Traversal in Python

Constructing a binary tree from preorder and inorder traversal sequences is a classic problem in tree algorithms. The key insight is that the preorder traversal gives us the root nodes in order, while the inorder traversal helps us determine the left and right subtrees.

3 9 20 15 7 Preorder: [3, 9, 20, 15, 7] Inorder: [9, 3, 15, 20, 7]

Algorithm Steps

The recursive algorithm follows these steps ?

  • Take the first element from preorder as the current root
  • Find the root's position in the inorder sequence
  • Elements to the left of root in inorder form the left subtree
  • Elements to the right of root in inorder form the right subtree
  • Recursively build left and right subtrees

Implementation

class TreeNode:
    def __init__(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right

def print_inorder(root):
    """Print tree using inorder traversal"""
    if root is not None:
        print_inorder(root.left)
        print(root.data, end=', ')
        print_inorder(root.right)

class Solution:
    def buildTree(self, preorder, inorder):
        if not inorder:
            return None
        
        # First element in preorder is always the root
        root = TreeNode(preorder.pop(0))
        root_index = inorder.index(root.data)
        
        # Build left subtree with elements before root in inorder
        root.left = self.buildTree(preorder, inorder[:root_index])
        
        # Build right subtree with elements after root in inorder
        root.right = self.buildTree(preorder, inorder[root_index + 1:])
        
        return root

# Example usage
solution = Solution()
preorder = [3, 9, 20, 15, 7]
inorder = [9, 3, 15, 20, 7]

tree = solution.buildTree(preorder, inorder)
print("Inorder traversal of constructed tree:")
print_inorder(tree)
Inorder traversal of constructed tree:
9, 3, 15, 20, 7, 

How It Works

Let's trace through the algorithm with our example ?

  1. Step 1: Root = 3 (first in preorder), split inorder at 3: [9] | [15, 20, 7]
  2. Step 2: Left subtree gets [9], right subtree gets [20, 15, 7] from preorder
  3. Step 3: For left: root = 9, no more elements
  4. Step 4: For right: root = 20, split at 20: [15] | [7]
  5. Step 5: Continue recursively until all nodes are processed

Time and Space Complexity

Aspect Complexity Explanation
Time O(n²) index() operation for each node
Space O(n) Recursion stack depth

Optimized Version

We can optimize by using a hashmap to store inorder indices ?

class OptimizedSolution:
    def buildTree(self, preorder, inorder):
        # Create index map for O(1) lookups
        inorder_map = {val: i for i, val in enumerate(inorder)}
        self.preorder_idx = 0
        
        def build(left, right):
            if left > right:
                return None
            
            root_val = preorder[self.preorder_idx]
            self.preorder_idx += 1
            root = TreeNode(root_val)
            
            inorder_idx = inorder_map[root_val]
            
            # Build left subtree first (preorder: root, left, right)
            root.left = build(left, inorder_idx - 1)
            root.right = build(inorder_idx + 1, right)
            
            return root
        
        return build(0, len(inorder) - 1)

# Test optimized version
optimized = OptimizedSolution()
preorder = [3, 9, 20, 15, 7]
inorder = [9, 3, 15, 20, 7]

tree = optimized.buildTree(preorder, inorder)
print("Optimized version result:")
print_inorder(tree)
Optimized version result:
9, 3, 15, 20, 7, 

Conclusion

Building a binary tree from preorder and inorder traversals uses the property that preorder gives us roots while inorder defines subtree boundaries. The optimized version with hashmap reduces time complexity from O(n²) to O(n).

Updated on: 2026-03-25T07:58:15+05:30

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements