Description
Construct Binary Search Tree from Preorder Traversal
Given an array of integers preorder, which represents the preorder traversal of a BST (i.e., binary search tree), construct the tree and return its root.
It is guaranteed that there is always possible to find a binary search tree with the given requirements for the given test cases.
A binary search tree is a binary tree where for every node, any descendant of Node.left has a value strictly less than Node.val, and any descendant of Node.right has a value strictly greater than Node.val.
A preorder traversal of a binary tree displays the value of the node first, then traverses Node.left, then traverses Node.right.
Example 1:

Input: preorder = [8,5,1,7,10,12]
Output: [8,5,10,1,7,null,12]
Example 2:
Input: preorder = [1,3]
Output: [1,null,3]
Constraints:
1 <= preorder.length <= 1001 <= preorder[i] <= 1000- All the values of
preorderare unique.
Recursive Upper Bound DFS ( Time, Space)
Intuition
Since every node in a BST enforces an upper bound limit on its left subtree:
- Maintain a global
indexpointer traversingpreorderleft-to-right. - Pass an
upperBoundparameter to recursive calls (initialized toInteger.MAX_VALUEfor the root). - At each step, if
indexreaches the end of the array ORpreorder[index] > upperBound, the current node cannot belong to this subtree, so returnnull. - Construct the root node:
TreeNode root = new TreeNode(preorder[index++]). - Recursively construct:
- Left Subtree: Values must be smaller than
root.valsetupperBound = root.val. - Right Subtree: Values must be smaller than the current parent’s
upperBoundkeepupperBound.
- Left Subtree: Values must be smaller than
class Solution {
private int index = 0;
public TreeNode bstFromPreorder(int[] preorder) {
return build(preorder, Integer.MAX_VALUE);
}
private TreeNode build(int[] preorder, int bound) {
if (index == preorder.length || preorder[index] > bound) {
return null;
}
TreeNode root = new TreeNode(preorder[index++]);
// Left subtree elements must be < root.val
root.left = build(preorder, root.val);
// Right subtree elements must be < parent's upper bound
root.right = build(preorder, bound);
return root;
}
}
Complexity
- Time Complexity: — Every element in
preorderis processed exactly once in time. - Space Complexity: — Recursion call stack depth bounded by tree height ( for balanced, for skewed).
Key Interview Talking Point
- Why not use binary search to split left/right subtrees? Finding the split point with binary search takes per node, leading to total time (or in skewed trees).
- The Upper Bound approach achieves optimal time by implicitly determining subtrees in a single linear pass.
Easy Memory Rule
“Track
indexglobally Passroot.valas upper bound for Left Subtree Keep original upper bound for Right Subtree!”