[Naive Approach] Using One by One Insert - O(n log n) Time O(1) Space
1. Create an empty BST 2. Traverse through the given pre array and one by one insert every item into the BST
Output
35 30 100 80 40
Time Complexity: O(n log n) Space Complexity: O(h)
[Better Approach] Using Find First Greater than Root - O(nΒ²)Time O(h) Space
The first element of preorder traversal is always the root. We first construct the root. Then we find the index of the first element which is greater than the root. Let the index be 'i'. The values between root (lowest index) and 'i' will be part of the left subtree, and the values between 'i'(inclusive) and 'n-1' will be part of the right subtree. Divide the given pre[] at index "i" and recur for left and right sub-trees.
For example in {10, 5, 1, 7, 40, 50}, 10 is the first element, so we make it root. Now we look for the first element greater than 10, we find 40. So we know the structure of BST is as follows.:
We recursively follow the above steps for subarrays {5, 1, 7} and {40, 50}, and get the complete tree.
Output
35 30 100 80 40
Time Complexity: O(n2) Auxiliary Space: O(n)
[Efficient Approach 1] Pass Range in Recursion - O(n) Time O(h) Space
The trick is to set a range {min .. max} for every node. We initialize range as [-inf, +inf]. We begin with the first element of the preorder traversal, create a node with the given key. Now moving forward, we set the range as [-inf, key] for left subtree and [key, inf] for right subtree.
Follow the below steps to solve the problem:
Initialize the range as {-inf , +inf}
The first node will definitely be in range, so create a root node.
To construct the left subtree, set the range as {-inf, root.key} and for right subtree as [root.key, +inf]
Output
35 30 100 80 40
Time Complexity: O(n) Auxiliary Space: O(n)
[Expected Approach - 2] Using Stack - O(n) Time O(h) Space
The Idea is that the first element of preorder traversal is always the root. We create the root node and push it into a stack. The stack is used to keep track of nodes whose right child is not yet assigned.
Now for every next element in preorder:
If the current value is less than the top of stack, it means it belongs to the left subtree, so we attach it as the left child of the stackβs top node.
If the current value is greater than the top of stack, we keep popping from the stack until we find a node smaller than the current value. The last popped node becomes the parent, and we attach the current node as its right child.
We push the current element into the stack.
After attaching, we push the current node into the stack.