in DS edited by
38,907 views
129 votes
129 votes

You are given the postorder traversal, $P$,  of a binary search tree on the $n$ elements $1, 2, \dots, n$. You have to determine the unique binary search tree that has $P$ as its postorder traversal. What is the time complexity of the most efficient algorithm for doing this?

  1. $\Theta(\log n)$
  2. $\Theta(n)$
  3. $\Theta(n\log n)$
  4. None of the above, as the tree cannot be uniquely determined
in DS edited by
38.9k views

4 Comments

Yes, but search time won't affect the asymptotic complexity -- please see the updated link at bottom of the answer.
3
3
Here elements are 1,2,3,..n hence we can found element in O(1) time in In-oder traversal .

hence it leads to O(n) time complexity.

But if the element set is [1,n] not sequential then to find element it takes O(logn).

hence in this case time worst case time complexity will be O(nlogn).

am i right @Arjun sir
1
1

No in any case it follows BST property so O(N) will be the answer

Here is very easy and intuitive explanation

https://gateoverflow.in/458/gate-cse-2008-question-46?show=406177#a406177

0
0

6 Answers

134 votes
134 votes
Best answer

Correct Answer: B

Last element in post order is the root of tree- find this element in inorder- $\log n$ time. 
Now as in quick sort consider this as pivot and  split the post order array into 2- possible because all elements smaller than pivot goes to left and all elements larger than pivot goes to right and suppose we have x elements smaller than pivot, these elements will be same in both inorder as well as postorder (order may change). We already got the root, now left child is the left split and right child is the right split. 

So, doing this recursively gives time complexity of this approach as 
$$T(n) = T(k) + T(n-k-1) + \log n$$

Solving would give $T(n) = O(n \log n)$ in worst case, by putting $k=0$ and shown at bottom.

But searching for an element in the inorder traversal of given BST can be done in $O(1)$ because we have $n$ elements from $1..n$ so there is no need to search for an element- if last element in post order is say $5$ we take it as root and since $4$ elements $(1..4)$ are smaller we split the post order array in to two- (first $4$ elements), ($6$th element onward) and solve recursively. Time complexity for this would be 

$$T(n) = T(k) + T(n-k-1) + O(1)$$

which gives $T(n) = O(n).$

Since we know that all elements must be traversed at least  once, $T(n) = \Omega(n)$ also and so $$T(n) = \Theta(n).$$ The following code is doing this. 

//Install graphviz (sudo apt-get install graphviz on Ubuntu) to view output tree
#include<stdio.h>
#include<stdlib.h>
struct tree
{
    struct tree* left;
    struct tree* right;
    int x;
};
struct tree* makenode(int x) 
{
    struct tree * root =  malloc(sizeof(struct tree));
    root -> x = x;
    root -> left = root -> right = NULL;
    return root;
}

struct tree* makeBST(int *post, int start, int n, int inorder){
    if(n <= 0)
            return NULL;
    int pivot = post[start + n -1];
    struct tree * root = makenode(pivot);
    root -> left = makeBST(post, start, pivot-1 - inorder, inorder );
    root -> right = makeBST(post, pivot - inorder - 1, n - (pivot - inorder), pivot);
    return root;
}
void preorder(struct tree* node)
{
    if(node == NULL)
        return;
    printf("%d ", node->x);
    preorder(node->left);
    preorder(node->right);
}
void printdot(struct tree* node, FILE * f)
{
    if(node == NULL)
        return;
    if(node-> left != NULL)
    {
        fprintf(f, "%d -- %d;\n", node->x, node->left->x);
    }
    if(node-> right != NULL)
    {
        fprintf(f, "%d -- %d;\n", node->x, node->right->x);
    }
    printdot(node->left, f);
    printdot(node->right, f);
}

int main(){
    int i, n, *a;
    printf("Enter n: ");
    scanf("%d", &n);
    a = malloc(n * sizeof(int));
    printf ("Enter post order traversal: ");
    for(i = 0; i < n; i++)
    {
        scanf("%d", &a[i]);
    }
    struct tree * tree = makeBST(a, 0, n, 0);
    printf("Pre order traversal is : ");
    preorder(tree);
    printf("\n");
    FILE * f = fopen("tree.dot", "w");
    fprintf(f, "graph tree { \n");
    printdot(tree, f);
    fprintf(f, "}\n");
    fclose(f);
    
    #if defined(__linux__) || (defined(__APPLE__) && defined(__MACH__) || (defined (__gnu_linux__)) )
        system("dot -Tpng tree.dot -o output.png; eog output.png");
    #endif

}

$$T(n) = T(k) + T(n-k-1) + \log n$$

Solving would give $T(n) = O(n \log n)$, by putting $k=0$,
$T(n) = T(0) +T(n-1) + \log n, \\\implies T(n) = O(1)+ \log n + \log (n-1) + \log (n-2) + \dots + \log 1\\\implies T(n) = n + \log n! \\\implies T(n) = O(n \log n).$

(Stirling's Approximation)

PS: Even for a general BST, given a post order traversal, we can construct the BST in $O(n)$ more stricter than $O(n \log n)$ derived above and this matches $\Omega(n)$ and hence we do have an $\Theta(n)$ algorithm. This algorithm can be seen at below link 
https://www.geeksforgeeks.org/construct-a-binary-search-tree-from-given-postorder/

edited by
by

70 Comments

" First element in post order is the root of tree- find this element in inorder- logn time. "
This statement is incorrect.

In post order the last element is the root of the tree. Also, to find the position of that element in InOrder will take constant time, coz it will be present at index $e-1$ where $e$ is the value of the element.

0
0
yes, it is last- corrected. The second statement is true- I have mentioned it already, but not in first paragraph to show that the time complexity won't change even if numbers are not from 1..n.
0
0

what is T(n) here?

How is it the time complexity to generate the BST whose post order traversal is $P$?

0
0
T(n) is the time complexity of the approach given n elements in post order array.
0
0

not able to understand how the req. BST is being generated.

0
0
Added code :)
0
0
         7
     /     \
    3      10
   / \     / \
  2   5   9   12
             /
            11

Inorder is: 2 3 5 7 9 10 11 12

Postorder is: 2 5 3 9 11 12 10 7

 

current = 7, split inorder at 7: 2 3 5 | 9 10 11 12

So now I have got 2 trees,  2 3 5 and 9 10 11 12,to construct the subtree  2 3 5 I need to find the root,which is the last element in the subset 2 5 3 in the postorder ,which wd take O(1) time.

How is this done in the code?

Plz explain Sir

 

 
0
0
I am extremely sorry for the fact that I am not able to allign the code with my example.If you can extend my example ,it would be helpful.:(
0
0

See the place of '7' in inorder. if we remove '7' inorder split occurs as you have shown and post order also splits in same position- first 3 elements in one array and next 4 in the next array. 

pivot = post[start + n -1];
root -> left = makeBST(post, start, pivot-1 - inorder, inorder );
root -> right = makeBST(post, pivot - inorder - 1, n - (pivot - inorder), pivot);

This split is done by the above 3 lines. 

We get the pivot- which here is 7. Now, we have to find the position of 7 in inorder list- which is not done in the code but assumed as pivot because in the question it is told that numbers are from $1..n$. Otherwise we would need to do a binary search and find pivot position. 

4
4
@Arjun,

here we know elements are 1..n so we dnt need to do additional binary search in Inorder to get pos of root :so its n*O(1)=O(n)

if its not of form 1...n then it will be n*O(logn)=O(nlogn).verify once
4
4
@Arjun  Can you tell me how the above recurrence is solved. I mean "k" is taken as constant or variable. If constant then further splitting of T(k) will generate another constant. Can you cLear this doubt.?
0
0
sir have u assumed that inorder will be given or the binary tree itself will be given . they are saying that they have given the postorder only .
0
0
@Anurag yes, you are correct. Worst case for general case would be $O(n \log n)$.

@Gate Just by trying values for $k$. I have added at end.

@Tendua Here, they have given inorder also- by saying numbers are from 1..n.
3
3
@Arjun some algorithms i recently came to know are giving Bst from given preorder or postorder in O(n).I have been following O(nlogn) previously.

which one should we answer fr gate ?
0
0
which is that algorithm? Also O(n) in worst case?
0
0
3
3
have to analyze that. $O(n)$ should be possible for postorder too. Let me see..
0
0
@arjun sir,can you please tell the base condition to solve this recurrence equation?

T(n) = T(k) + T(n-k-1) + O(logn)

and also,how in the last you have solved that recurrence equation??
0
0
can you pls tell for which calulation ,you are multiplying 'n' with O(1)??
0
0
Is it clear now? Even I dont remember how I did like that earlier :O
0
0
no arjun sirr,its still not cleared..can u pls tell the base condition for the recursion?
0
0
sir,can you pls check this:

we are given postorder,so last element is the root.suppose 'X' is the last element,so from 1...n,1 to x-1 form left subtree and x+1 to n form right subtree.this takes O(1) time as we are given that elements are from 1,2...n so we dont need to search for the root in inorder.

after this take each node and then traverse the postorder from right to left to find the next root of the subtree which will take O(n) time.

 

i am not able to think after this..pls guide me how to proceed after this
0
0
Base condition is $T(1) = O(1)$.

At each step of recursionwe only do what you told- that is find the left and right subtrees. Then same thing is done recursively. So, ineffectively we are doing a tree construction here. Complexity is same as that of tree traversal.
1
1
If we did quick sort for finding root position it will take o(n) time. it should be included in reccurence
0
0
HOw to think like this in exam hall :(
1
1
@arjun sir will the answer change if the question is changed a bit ?
"Given preorder and innorder calculate postorder"
0
0
@Dulqar no change.

@gokou Even the smartest of people wont be able to do that. But that is the purpose of learning. This is not an unknown problem and those in good colleges would have seen this.
0
0
Each time pivot is fixes the root  and left of pivot is left subtree and right of pivot is right subtree , Right ?

This method seems to be working . but How u got that recurrance relation ? and how to solve that . is stilla mystry for me  :(
0
0
The first recurrence? It is straight forward- once the root is found we recurse to its 2 child trees - if one has $k$ nodes, other will have $n-k-1$ nodes.
1
1
yes sir, i too could  understand  upto that . but no clue  with log n addition part.
And solution of the recurrence .
0
0
$\log n$ is the time to find the root. For this question, solution to that recurrence is not needed. It is derived by substituting value for $k$. For the second recurrence there is a trick - for each division one element goes from $n$ and complexity adds by $O(1)$. So, maximum it can add up to $O(n)$.
5
5
Answer should be D. As inorder traversal is not given, and thus tree can not be determined uniquely.

Please tell me if I am wrong.
0
0

@Arjun sir as we can construct a unique bst just from its postorder traversal then why we need to look at inorder traversal at all because by looking at inorder traversal will increase the complexity when a number are not 1,2,3.....n because in that case, we will have to search an element in inorder traversal using binary search that will take logn time as in that case location will not be value of an element -1 . So can't we just use postorder and use the above algorithm so that in general case also complexity will be same i.e o(n)????

1
1

@abk1115 

we can construct a unique bst just from its postorder traversal

who told this?

0
0
What is the answer? b or c?
0
0
What i can understand from above is that for this problem answer is 0(n) because inorder search is 0(1).And every time when we choose root and call for left and right ,right will be empty tree and left will have n-1 nodes.

But for general case you mentioned it is nlogn. but the geeksforgeeks has given 0(n) solution for pre order.And they claim that same can be modified to handle postorder also in 0(n).Please help here @Arjun sir
0
0
i think it should be "split inorder array into two parts" in second line...
0
0
@vinay125

Inorder traversal of a BST is always sorted order.So , unique tree can be constructed.
0
0
Exactly same point.
0
0
Yes , we can.
0
0
edited by

@Arjun Sir, the code seems to fail on the case of P = [1,3,5,4,2]. I modified the start of right subtree as start + (n-(pivot-inorder)) and set a check for start at the beginning of the function to fix it.

1
1
As we have given elements of BST are 1 to n. Inorder of a BST is sorted. So, inorder traversal will be 1,2,3,4....n
0
0

we can construct a unique bst just from its postorder traversal

I think it is correct as it is mentioned that it is a bst so by sorting elements of postorder traversal we can find inorder .

So from inorder and postorder we can construct unique bst.

0
0

@Arjun sir as it is mentioned that it is a bst so by sorting elements of postorder traversal we can find inorder .

So from inorder and postorder we can construct unique bst.

Where i am getting wrong?

0
0

@Verma Ashish

PreOrder, PostOrder or InOrder all will takes O(n) time.

because, here we traverse every node once.

right?? 

0
0
Yes. Time complexity of preorder, inorder and postorder traversals is O(n).

But this question is about constructing unique bst from inorder and postorder
0
0
So, what will be difference??
0
0
edited by

Here we have to look into both post order and inorder for making decision for a node.. And I'm not able to understand the code given in the answer..

Even if it is not bst and we have inorder and postorder then also there is a solution given here which uses hashing and construct tree in O(n)

0
0

@Verma Ashish

Code is nothing but simple a BST creation. Isnot it??

In hashing search time is O(1), good than other algo. but how create an BST with hashing?? Can u plz give the hint. 

0
0

Code is nothing but simple a BST creation. Isnot it??

Yes.. but it is difficult for me to analyze time complexity of given code.

By using efficient procedure we can reduce search time..which is done on geeksforgeeks..(by using hashing). In simple searching an element from inorder of a bst can be found in O(logn). (O(n) if it is not bst)

I have no idea about there implimentation(hashing and all..)   (。•́︿•̀。)

0
0
See in this code we have to visit every node.

So, T.C.=$O\left ( n \right )$

right??
0
0
Here we have to check every element from postorder and for that element we have to search in inorder..

So for naive approach O(nlogn) time complexity is more intuitive.. But as explained in the answer it can be done in O(n).
0
0

why nlogn? I mean why logn need to be multiplied??

Even code is giving some internal error

Check :https://ideone.com/BBEIIJ

0
0
ma'am see the starting and ending part of answer..
0
0

@Verma Ashish

Can u tell me meaning of this line?

Last element in post order is the root of tree- find this element in inorder- logn time.  

Only for this line it is taking log n , rt??

ckeck here this code working fine :) https://ideone.com/URDpMI 

0
0
Since it is a bst therefore inorder will be in sorted order so we can apply binary search on inorder (O(logn)). Let's say element is x then after finding x inorder will be splitted in two parts -- elements less than x form left subtree and elements greater than x goes to right subtree.

Recursively this procedure is applied on left subtree and right subtree also..

Thanks for the code :)
3
3
yes, but why do we need binary search??

See, $T(n)=T(k)+T(n-k-1)$

here $T(k)$ will be left subtree and $T(n-k-1)$ will be right subtree. So, why extra binary search will be needed?? We need to traverse every node, na??
3
3

Yes.. you are right..here we don't need searching.. 

In answer also this thing is mentioned-

searching for an element in the inorder traversal of given BST can be done in O(1) because we have n elements from 1..n so there is no need to search for an element- if last element in post order is say 5 we take it as root and since 4 elements (1..4) are smaller we split the post order array in to two- (first 4 elements), (6th element onward) and solve recursively. Time complexity for this would be 

 

T(n)=T(k)+T(n−k−1)+O(1)

which gives T(n)=O(n)

4
4

yes, that is what I got.

Can u got why prev code is giving internal error?? If u got it, plz tell me too.

0
0
I didn't get that..
0
0
worst case-- how is it n * O(logn) ?? we are just performing binary search once in the Inorder list to find the root !
0
0
@Verma Ashish I am not getting the fact that why we are mentioning inorder continuously what role is that playing here??
0
0
sir if we sort the post order then time complexity will become nlogn
0
0
Why does no free academy discuss such questions on YouTube?
1
1

Given a preorder to construct BST we need O(n) also,

Link:https://www.geeksforgeeks.org/construct-bst-from-given-preorder-traversa/

2
2

@gatecse @Arjun @Shaik Masthan @Sachin Mittal 1 @shishir__roy sir we are doing k=0 just considering it as left skewed or right skewed tree?

0
0
Great Explanation :)
0
0

This might be hepful for more visualisation.

https://youtu.be/UmJT3j26t1I

4
4

@samarpita k=0 taken to have a worst case scenario into consideration 

0
0
45 votes
45 votes

I don't think it's a very difficult question. The algorithm of finding a number in inorder traversal using binary search is just inefficient. As tree given is a Binary Search Tree and postorder traversal is given, we know last element is the root.

Start from last element down to first element (that is read postorder traversal in reverse), and construct a BST like you normally do following the BST property i.e. if element is less than root, add it as left node and if the element is greater than root add it on right. Do this recursively, by passing the correct ranges in which the number should lie (fulfilling BST property). It will be the required BST. This takes traversing the postorder traversal once O(n) creating n recursive calls doing O(1) work of adding one node at a time. 

And I am sure you have applied this already with preorder in many questions. Given the preorder of a BST, you just parse it from left to right and create a unique BST with hand in O(n) time (without using quicksort and pivot). 

Link for reference of ranges: 

http://algorithms.tutorialhorizon.com/construct-binary-search-tree-from-a-given-preorder-traversal-using-recursion/

4 Comments

[if we are building a tree from given list], then

for inserting 'n' nodes in a binary search tree in avg case we need O(nlogn) time,

the complexity of traversing post order list will be O(n), but inserting will have separate complexity of O(nlogn).

correct me if i am wrong..
3
3

As far as I remember, idea was to use BST min max algorithm to recursively put values into the BST. It passes ranges of max and min values along with root to insert an element. You can refer to the link given in post or this link:
http://www.geeksforgeeks.org/construct-bst-from-given-preorder-traversa/
(2nd method in this post) -> O(n) time. 
And I felt like this is what we intuitively do while solving GATE questions on BST instances. If this doesn't make sense, there is also an O(n) stack solution in which you can actually see why it's not O(n^2).

0
0
thank you for link
0
0
great
0
0
27 votes
27 votes

Here is the Stack's based Iterative solution that works in O(n) time..

Construct BST from given Postorder Traversal.  ( traverse given postorder in reverse)

  1. Create an empty Stack.
  2. Start from last element and make it as root. Push it into the stack.
  3. If the next value  is greater than stack's top value, make it as right child of Stack's top node. Push the node to the stack.
  4. Continue popping while Stack is not empty and the next value is less than Stack's top value. Make this value as left child of last popped node. Push the new node to the stack.
  5. Repeat steps 3 and 4 until no item is left in given postorder array of elements.

We can also perform similar technique for preorder,

Construct BST from given Preorder Traversal

  1. Create an empty stack.
  2.  Make the first value as root. Push it to the stack.
  3. Keep on popping while the stack is not empty and the next value is greater than stack’s top value. Make this value as the right child of the last popped node. Push the new node to the stack.
  4.  If the next value is less than the stack’s top value, make this value as the left child of the stack’s top node. Push the new node to the stack.
  5. Repeat steps 3 and 4 until no item is left in given preorder array of elements.

Since,every item is pushed and popped only once. So at most 2n push/pop operations are performed for n elements.Therefore, time complexity is O(n).

Thus for any P as postorder traversal, in order to determine the unique BST, the most efficient algorithm takes O(n).

4 Comments

@Meghna-How your stack method works?

Consider I have order 1, 7, 5, 50, 40, 10

My next element to be considered in postorder is 1.

stack contents are 7->5(from top to bottom)

Now, 1 will cause the stack to become empty as per your algorithm

how 1 will be placed in the bst then?
0
0

@Ayush Upadhyaya when you have element 1 left in the postorder and stack contains 7->5 (top to bottom) than pop out all the elements from stack (i.e pop 7 then pop 5) and make 1 as left child of last popped element i.e 5.

2
2

Okay convinced!. But this method will always guarantee that the bst I will get is "unique" for the postorder traversal given? 

0
0

I think the uniqueness of the tree is determined if we're able to separate the left sub tree and the right tree with the given tree traversals. In-order does exactly the same, by segregating the LST, then root then RST.So with any given order (pre-order, post-order, level order), we always know where to place the node, creating no ambiguity. So as per this method is concerned, we are always sure about where to place the node, making it generate a unique tree with no ambiguity. 

Proof: why In-order (+ pre, post or level) generates unique tree. (though very complex to understand):https://stackoverflow.com/questions/30556590/how-does-inorderpreorder-construct-unique-binary-tree

This may also help:https://stackoverflow.com/questions/33062228/why-it-is-impossible-to-construct-binary-tree-with-pre-order-post-order-and-lev

4
4
7 votes
7 votes
take any example and try to create BST by adding one by one element in given sequence(preorder then first to last element and postorder then reverse) everytime you ended up with correct BST. Bcoz here by adding we follow two rules 1)we will compare value(BST property) 2) by following sequence we are sure that created tree will have same pre/postorder as given

so Time Complexity of creating such BST from given pre/postorder is O(n) all time.
Answer: