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. For example:
preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
should return the following tree:
3
/ \
9 20
/ \
15 7
Another example:
preorder = [-1], inorder = [-1]
should return a tree with root -1
.
Describe an algorithm to efficiently construct the binary tree given these two traversals. What is the time and space complexity of your solution? What edge cases should be taken into account?
For each element in preorder
, we'd search for it in inorder
. The index of this element in inorder
would tell us how many elements are in the left subtree. We could then recursively build the tree. However, the constant searching in inorder
makes this approach very inefficient.
Time Complexity: O(N^2) in the worst case, where N is the number of nodes. Space Complexity: O(N) for the recursion stack.
preorder
array to determine the root node and the inorder
array to determine the structure (left and right subtrees) of the tree. A HashMap
to store the indices of the inorder
array allows for O(1) lookup during tree construction.HashMap
that stores the index of each value in the inorder
array.preorder
array, which is the root of the tree.inorder
array. This index divides the inorder
array into left and right subtrees.preorder
and inorder
arrays corresponding to the left subtree.preorder
and inorder
arrays corresponding to the right subtree.preorder
or inorder
arrays: return null
.import java.util.HashMap;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val) {
this.val = val;
}
}
public class Solution {
int preorderIndex = 0;
HashMap<Integer, Integer> inorderIndexMap;
int[] preorder;
int[] inorder;
public TreeNode buildTree(int[] preorder, int[] inorder) {
this.preorder = preorder;
this.inorder = inorder;
inorderIndexMap = new HashMap<>();
for (int i = 0; i < inorder.length; i++) {
inorderIndexMap.put(inorder[i], i);
}
return arrayToTree(0, preorder.length - 1);
}
private TreeNode arrayToTree(int left, int right) {
if (left > right)
return null;
int rootValue = preorder[preorderIndex++];
TreeNode root = new TreeNode(rootValue);
root.left = arrayToTree(left, inorderIndexMap.get(rootValue) - 1);
root.right = arrayToTree(inorderIndexMap.get(rootValue) + 1, right);
return root;
}
}
Time Complexity: O(N), where N is the number of nodes in the tree. We visit each node once.
Space Complexity: O(N) in the worst case. This is due to the HashMap
which stores all the inorder
elements, and the recursion stack which can go as deep as N in a skewed tree. In a balanced tree, the recursion stack space is O(log N).