Google Interview Question for Software Engineer / Developers






Comment hidden because of low score. Click to expand.
0
of 0 vote

* Flatten trees into sorted lists.
* Merge sorted lists.
* Create tree out of merged list.

IIRC, that is O(n1+n2).

- anonymus March 26, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

I don't think this is an inplace sorting, you're creating an altogether new tree. One way is to take one tree as base tree (I call it tree 1) and traverse the elements of tree 2 in inorder fashion, and insert the elements onto tree 1. Destroy tree 2 at the end of this operation.

The order of this operation will be O(n2) - linear.

- JustStarted March 26, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

The initial answer seems correct.

Its just from the resultant linked list the middle node would be given as root.
One disadvantage of this solution is that from the resultant tree the search operation would be O(n).
As the resultant tree would look like
4
/\
3 5
/ \
2 6
/ \
1 7

- searching March 27, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Can anyone please explain me what's the problem in "JustStarted" solution.

- neo April 01, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

* Flatten trees into sorted lists.
* Merge sorted lists.
* Create tree out of merged list.

this idea is totally right, the tree can be used as list..

- haha April 05, 2011 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

This is not linear as creating a tree takes O(nlgn) time. If we could create tree in O(n) time then we can do sorting in O(n) time. ;-)

- Abhishek April 24, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

we could do it in O(m+n) (m, n sizes of both bsts)
1) Covert Tree1 in to circular doubly linked list. O(m)
Search for "tree list recursion problem" for more details.
2) Convert Tree2 in to circular doubly linked list O(n).
3) Merge Tree1, Tree2 O(m+n)
4) Convert the merged circular doubly linked list to Tree. O(m+n) (Middle node can be chosen as root to make tree balanced).

- Anonymous May 22, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Here is C code.

/**************************************************************
**
**  Auto-generated to help solve interview questions.
**
**  Question : 
    You have two BST, you have to merge them into a single BST, inplace
and linear time. 
***************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <unistd.h>

/* Define Node */
struct node {
    int data;
    struct node *left;
    struct node *right;
};
typedef struct node* ND;

/* Tree insert */
void bt_insert( ND *tree, int data)
{
    ND p,q;
    q = p = *tree;
    while(p != NULL)
    {
        q = p;
        if( data > p->data)
            p = p->right;
        else
            p = p->left;
    }
    p = (ND) malloc( sizeof(struct node ));
    p->data = data;
    p->left = NULL;
    p->right = NULL;
    if (*tree == NULL)
    {
        *tree = p;
    }
    else
    {
        if( data > q->data )
            q->right = p;
        else
            q->left = p;
    }
}
/* convert binary tree to list*/
void bt_list(ND *head)
{
    ND first, last, t, tree;
    tree = *head;

    if( tree == NULL)
        return;

    // Store right leaf as we will overwrite it..
    t = tree->right;

    // Both leafs null, just point them to trunk and return;
    if( tree->right == NULL && tree->left == NULL)
    {
        tree->left  = tree;
        tree->right = tree;
        return;
    }
    // Non null left leaf
    // Recursively, list the left tree.
    // tree should point to the last node in the list.
    if( tree->left != NULL)
    {
        bt_list(&tree->left);
        last = tree->left;
        first = last->right;
        tree->right =  first;
        tree->left = last;
        first->left = tree;
        last->right = tree;
    }
    else
    {
        first = last = tree;
        last->left = tree;
        last->right = tree;
    }
    if( t != NULL)
    {
        bt_list(&t);
        // tree is last now.
        tree->right = t->right;
        t->right->left = tree;
        t->right = first;
        first->left = t;
        *head = t;
    }
}
/* print bt */
void bt_print( ND tree)
{
    if( tree != NULL)
    {
       bt_print(tree->left);
       printf("%d \t", tree->data);
       bt_print(tree->right);
    }
}
/* print list */
void lt_print( ND tree)
{
    ND t=NULL;
    while( tree != t)
    {
        if(t == NULL)
        {
            t = tree;
        }
        printf("%d \t", tree->right->data);
        tree = tree->right;
        if( tree->right->left != tree  || tree->left->right != tree)
            printf("Broken Link");
    }
    printf("\n");
}
/* convert list to tree */
void lt_tree( ND *list)
{
    ND  first, last;
    int len=1;
    // Find mid point
    if( *list == NULL)
        return;
    last = *list;
    first = last->right;
    while(first != last)
    {
        first = first->right;
        len++;
    }
    if( 1 == len)
    {
        first->right = NULL;
        first->left  = NULL;
        return;
    }
    len /= 2;
    while(len)
    {
        first = first->right;
        len --;
    }
    // first now represents the last of new left list.
    // set the root of tree.
    *list = first->right;
    // creating left list
    first->right = last->right;
    first->right->left = first;
    // create right list only if there is a right node.
    if( (*list)->right  != first)
    {
        last->right = (*list)->right;
        last->right->left = last;
    }
    else
    {
        (*list)->right = NULL;
        last = NULL;
    }
    lt_tree(&first);
    (*list)->left = first;
    if( last != NULL)
    {
        lt_tree(&last);
        (*list)->right = last;
    }
}
/* Merge two dlls */
lt_merge(ND *l1, ND *l2)
{
    ND l=NULL;
    ND p1, p2,p, t;
    if( *l2 == NULL)
    {
        return;
    }
    if( *l1 == NULL)
    {
        *l1 = *l2;
        return;
    }
    p1 = (*l1)->right; p2 = (*l2)->right;

    while( p1 != NULL && p2 != NULL)
    {
        if( p1->data <  p2->data)
        {
             t = p1;
             p1 = p1->right;
             if( t != p1)
             {
                 p1->left = t->left;
                 t->left->right = p1;
             }
             else
             {
                 p1 = NULL;
             }
        }
        else
        {
             t = p2;
             p2 = p2->right;
             if( t != p2)
             {
                 p2->left = t->left;
                 t->left->right = p2;
             }
             else
             {
                 p2 = NULL;
             }
        }
        if( l == NULL)
        {
            t->right = t->left = t;
        }
        else
        {
            t->right = l->right;
            l->right->left = t;
            l->right = t;
            t->left = l;
        }
        l = t;
    }
    if( p1 != NULL )
    {
        t = p1->left;
        
        t->right = l->right;
        l->right->left = t;
        l->right = p1;
        p1->left = l;
        l = t;
    }
    if( p2 != NULL )
    {
        t = p2->left;
        
        t->right = l->right;
        l->right->left = t;
        l->right = p2;
        p2->left = l;
        l = t;
    }
    *l1 = l;
}
int main()
{
  int i,r;
  ND tree1 = NULL, tree2 = NULL;

  for( i =0; i < 10; i++)
  {
      r = random()%100;
      bt_insert(&tree1, r);
      r = random()%100;
      bt_insert(&tree2, r);
  }

  printf("\nTree1: ");
  bt_print(tree1);

  printf("\nTree2: ");
  bt_print(tree2);
  printf("\n");

  // convert to lists
  bt_list(&tree1);
  bt_list(&tree2);
  // merge list
  lt_merge(&tree1, &tree2);
  // revert back to a tree.
  lt_tree(&tree1);


  printf("Tree:");
  bt_print(tree1);
  printf("\n");
  return 0;
}

- Mohan February 17, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

--- REMOVED ---

- Anurag Singh March 26, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

It's not that easy. You may violate the property of BST after the method you mentioned.

- Anonymous March 26, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Yes, True. My above solution will violate the property of BST.
Following should do:
If BSTs are A and B then:

Merge(A,B)
{
If A has only one node, insert into B.
If rootA < rootB then
rightA = A.right
A.right = NULL
Merge(A,B.left)
Merge(rightA,B)
Else
leftA = A.left
A.left = NULL
Merge(A,B.right)
Merge(leftA,B)
}

- Anurag Singh March 26, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Lets call the 2 trees A and B. Say we want to merge tree A into tree B. We can search for the value of root A in B, till we end up at some leaf. At this point we know either value of root(A) is greater/lesser than the value in the leaf. Say, value of root(A) is lesser. Then take the whole tree A and append it to the left-child of that leaf.

Now, compare the value of right child of root(A), snap the like between the child and root(A), and perform the same operation as above now comparing the snapped child's value with the elements in tree B and appending them to one of the leaves.

- betacod3r March 27, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Its not necessary that u'll end up with leaf while inserting and also its not linear. its O(mlogn) where m=|A| and n=|B| and worst is O(mn) if both the tree are right skewed having root of A is greater then rightmost child of B. or both tree are left skewed and root of A is smaller than leftmost child of B.

- Tulley March 27, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Ok, few points.

1. You are correct. We may not always end up in a leaf. But, if we dont end up in a lead, we may end up at a node with only one child. That, would mean the root(A) will become that child. ( depending on whether we chose to walk down the max/min path)

2. Your analysis is incorrect, since I walk through only tree(B), and just attach the root node of A to one of the nodes in B. Therefore, at most the algorithm will only walk through all nodes in B. Therefore, it is linear.

3. I think point 2 answers the skewness of the tree as well.


I will try to post a code which would explain this better.

- betacod3r March 27, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Also, these steps could become recursive. But, still would remain linear. There is a similar algo explained at this link.

discuss.joelonsoftware.com/default.asp?interview.11.506320.10

- betacod3r March 27, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Tulley ,i think we will always end up at a leaf.
can u give an example when this case is not true?

- Anonymous December 23, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

For each node in postfix traversal of T1, insert the node into T2.

- Anonymous March 28, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Pay attention to the requirements,the algorithm must be inplace and linear time.

- lshmouse March 28, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

To make it inorder, we can modify the code of Postfix, such that instead of returning the data, it returns the address of the node. We can add this mode in the tree 2.

- SAN April 18, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

insertion of each node takes O(lgn) time. Total time to insert all nodes of tree(A) into tree(B) will take O(nlgn) time. This is not linear.

- Abhishek April 24, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

struct node * root1,* root2;
void insertBST(struct node * root, struct node * ptr);
struct node * mergeBST(struct node * root1, struct node * root2)
{	
	//traverse root1 in postorder
	if(root1==NULL)return root2;
	if(root2==NULL)return root1;
	mergeBST(root1->left,root2);
	mergeBST(root1->right,root2);
	insertBST(root2,root1);
	return root2;
}

void insertBST(struct node * root, struct node * ptr)
{
	struct node * p,*q;
	p=root;
	q=NULL;
	ptr->left=ptr->right=NULL;
	while(p)
	{
		q=p;
		if(ptr->info<p->info)
			p=p->left;
		else
			p=p->right;
	}
	if(ptr->info<q->info)
		q->left=ptr;
	else
		q->right=ptr;
}

- chirag May 02, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

elegant but not linear time (also uses stack-space via recursion).

- yemre_ankara November 22, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

@chirag..can u please explain the algo with example ..man take two binary search tree & then please explain ..please reply asap.thanks in advance

- Algoseekar May 10, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

algoseekar,

intuition is to reach down to leaf-nodes by post-traversal, dettach them and insert into the second one. You need to visualize post-traversal on a simple tree and see that it tears apart the leaf nodes first so that no interval node deletion is to be handled and stuff.

- yemre_ankara November 22, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

faltten the lists in O(n) O(1)
merge to a bigger list O(n1+n2)
construct tree from merged list maintaini ng the balanced property

- sreeram January 13, 2013 | Flag Reply


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More