You are given two integer arrays, preorder
and inorder
, representing the preorder and inorder traversals of a binary tree, respectively. Your task is to reconstruct the binary tree from these traversals.
Input:
preorder
: An array of integers representing the preorder traversal of the tree.inorder
: An array of integers representing the inorder traversal of the tree.Output:
Constraints:
preorder
and inorder
are equal.Example:
preorder = [3, 9, 20, 15, 7]
inorder = [9, 3, 15, 20, 7]
In this example, the tree to construct is:
3
/ \
9 20
/ \
15 7
Explain your approach, its time and space complexity, and provide the code. Consider edge cases such as empty input arrays and single-node trees. How would you handle potentially invalid inputs where the preorder
and inorder
arrays do not represent the same tree?
Given two integer arrays preorder
and inorder
where preorder
is the preorder traversal of a binary tree and inorder
is the inorder traversal of the same tree, construct and return the binary tree.
The naive approach would involve iterating through the preorder
array and for each element, searching for it in the inorder
array. Once the element is found in inorder
, the left and right subtrees can be determined based on the elements to the left and right of the element in the inorder
array. This approach would be highly inefficient due to the repeated searching in the inorder
array.
The optimal approach uses a recursive algorithm combined with a hash map to store the indices of the inorder
array elements. This allows for quick lookups during the tree construction. Here's a breakdown:
inorder
array in a hash map for O(1) access.preorder
is always the root of the current subtree.inorder
array using the hash map.inorder
form the left subtree, and the elements to the right form the right subtree.preorder
and inorder
arrays.class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def buildTree(preorder, inorder):
inorder_map = {val: i for i, val in enumerate(inorder)}
preorder_index = 0
def build_subtree(inorder_start, inorder_end):
nonlocal preorder_index
if inorder_start > inorder_end:
return None
root_val = preorder[preorder_index]
root = TreeNode(root_val)
preorder_index += 1
inorder_index = inorder_map[root_val]
root.left = build_subtree(inorder_start, inorder_index - 1)
root.right = build_subtree(inorder_index + 1, inorder_end)
return root
return build_subtree(0, len(inorder) - 1)
preorder = [3, 9, 20, 15, 7]
inorder = [9, 3, 15, 20, 7]
root = buildTree(preorder, inorder)
# The 'root' variable now holds the constructed binary tree.
preorder
or inorder
is empty, return None
.preorder
and inorder
do not represent the same tree (e.g., different lengths or inconsistent values), the algorithm may produce an incorrect tree or enter an infinite loop (though the problem statement guarantees valid input).