Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Selected Reading
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.
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 ?
- Step 1: Root = 3 (first in preorder), split inorder at 3: [9] | [15, 20, 7]
- Step 2: Left subtree gets [9], right subtree gets [20, 15, 7] from preorder
- Step 3: For left: root = 9, no more elements
- Step 4: For right: root = 20, split at 20: [15] | [7]
- 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).
Advertisements
