Google Interview Question for Software Engineer / Developers






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

The right solution, already tested.

Idea, inorder travel two binary trees at the same time, and output the smaller one.

void print_two_binary_trees(Node* root1, Node *root2){
     bool done = false;
     Node *cursor1 = root1, *cursor2= root2;
     stack<Node*> s1,s2;
     while(!done)  {
         if(cursor1 != NULL && cursor2 != NULL)       {
             s1.push(cursor1);
             cursor1 = cursor1->left;       
             s2.push(cursor2);
             cursor2 = cursor2->left;        
         }
         else if(cursor1 != NULL && cursor2 == NULL)       {
             s1.push(cursor1);
             cursor1 = cursor1->left;              
         }                    
         else if(cursor1 == NULL && cursor2 != NULL)       {    
             s2.push(cursor2);
             cursor2 = cursor2->left;        
         } 
         else if(cursor1 == NULL && cursor2 == NULL)       {
             if(!s1.empty() && s2.empty())   {
                 cursor1 = s1.top();
                 s1.pop();
                 cout << cursor1->data<<" ";
                 cursor1 = cursor1->right;          
             }
             else if(s1.empty() && !s2.empty())   {
                 cursor2 = s2.top();
                 s2.pop();
                 cout << cursor2->data<<" ";
                 cursor2 = cursor2->right;          
             }
             else if(!s1.empty() && !s2.empty())   {
                  if(s1.top()->data <= s2.top()->data)   {
                      cursor1 = s1.top();
                      s1.pop();
                      cout << cursor1->data<<" ";
                      cursor1 = cursor1->right;             
                  }
                  else {
                       cursor2 = s2.top();
                      s2.pop();
                      cout << cursor2->data<<" ";
                      cursor2 = cursor2->right;                         
                  }
             }
             else {
                 done = true;     
             }
         }                                   
     }
     
}

P.S
Inorder travel one tree will output the elements in one tree in ascending order

void stack_inorder_visit(Node *root){
     bool done = false;
     stack<Node*> s;
     Node* cursor = root;
     while(!done) {
      if(cursor != NULL)
      {
         s.push(cursor);          //place pointer to node on the stack
                                  //before traversing the node's left subtree
         cursor = cursor->left; //traverse the left subtree
      }
      else                        //backtrack from the empty subtree and
                                  //visit the node at the top of the stack;
                                  //however, if the stack is empty, you are
                                  //done
      {
         if (!s.empty())
         {
             cursor = s.top();
             s.pop();
             cout << cursor->data<<" ";
             cursor = cursor->right;
         }
         else
             done = true;
      }     
     }
     
}

- Nova2358 January 24, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

inorder + merge(merge in mergesort)


using namespace std;
struct Node{
int val;
Node* left;
Node* right;
};
void inorder(Node* T1, Node* T2)
{
Node* cursor1 = T1;
Node* cursor2 = T2;
bool done = false;
stack<Node*> s1;
stack<Node*> s2;
while (!done)
{
if (cursor1)
{
s1.push(cursor1);
cursor1 = cursor1->left;
}
else if (cursor2)
{
s2.push(cursor2);
cursor2 = cursor2->left;
}
else
{
if (!s1.empty() && !s2.empty())
{
if (s1.top()->val < s2.top()->val)
{
cursor1 = s1.top()->right;
s1.pop();
}
else if (s1.top()->val > s2.top()->val)
{
cursor2 = s2.top()->right;
s2.pop();
}
else
{
cout << s1.top()->val << endl;
cursor1 = s1.top()->right;
s1.pop();
cursor2 = s2.top()->right;
s2.pop();
}
}
else
{
done = true;
}
}
}
}

- wenlei.zhouwl May 16, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Nova2358 : Can this be done using recursion instead of using explicit stacks,
like the regular BST traversal works.

- mytestaccount2 September 12, 2013 | Flag
Comment hidden because of low score. Click to expand.
2
of 2 vote

Simple and sweet

function printSorted($node1, $node2) {
    $current1 = $node1;
    $current2 = $node2;
    $stack1 = new Stack();
    $stack2 = new Stack();
    
    
    while (true) {
        if ($current1 || $current2) {
            if ($current1) {
                $stack1->push($current1);
                $current1 = $current1->left;
            }
            if ($current2) {
                $stack2->push($current2);
                $current2 = $current2->left;
            }
            continue;
        }
        
        if ($stack1->isEmpty() && $stack2->isEmpty()) {
            break;
        }
        
        if ($stack1->top() < $stack2->top()) {
            $next = $stack1->pop();
            $current1 = $next->right;
        } else {
            $next = $stack2->pop();
            $current2 = $next->right;
        }
        echo $next->data . "\t";
    }
}

- Sem April 08, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

void PrintMerged(struct node* root1, struct node* root2)
{
   if(root1 == NULL || root 2 == NULL)
     return; 

   PrintMerged(root1->left);
   PrintMerged(root2->left);

   if(root1->data < root2 -> data)			
   {
      cout << root1->data;
      PrintMerged(root1->right);
   }	
   else
   {
     cout << root2->data;
     PrintMerged(root2->right); 	
   }

}

let me know of any errors.

- abrahm July 22, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

If everything in 1 tree is smaller than everything in tree2 then this will print out everything in tree1 but stop never anything in tree2

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

EDIT: ... print out everything in tree1 then stop and never print out anything from tree2

- Anonymous July 28, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

A very basic error - Your method takes two arguments but you invoke it with only one argument

- Sandy July 22, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

What abrahm has written is correct (just that the function calls must contain 2 arguments like PrintMerged(root1->left,root2) and PrintMerged(root1,root2->left)).

It's basically a Merge Sort for trees. Just like we'd do for sorted arrays A[] and B[] - take 2 pointers *a and *b to the end of each array and compare elements and decrease the respective pointers to merge the array together.

Here with trees, we do the same. A Search tree is sorted because the in-order traversal printing yields sorted numbers.

So here we simultaneously start doing in-order traversal on both trees and print the lesser number.

abrahm's recursive function can be made non-recursive using a user-defined stack.

- Code_Monkey July 22, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Can anyone paste the working code?

- Anonymous July 22, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

abrahm will not work. -- you can't treat two trees on a single stack. One possible way would be to make this multithreaded.

- Anonymous July 23, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote
I have absolutely no idea how abrahm's code is supposed to work. I've looked at it for ages, but it's fundamentally flawed. Dood above me's got the right idea - you just can't make this happen like that. Perhaps iteratively you could do it, but I went for a very simple solution O(n): {{{ #include <list> #include <iostream> #include <algorithm> #include <iterator> using namespace std; typedef struct TreeNode { int v; struct TreeNode* l; struct TreeNode* r; TreeNode(int value, struct TreeNode* left, struct TreeNode* right) : v(value), l(left), r(right) { } } TreeNode; void treeToList(const TreeNode* n, list<int>& l) { if (n == 0) return; treeToList(n->l, l); l.push_back(n->v); treeToList(n->r, l); } void print(const TreeNode* a, const TreeNode* b) { list<int> listA, listB; treeToList(a, listA); treeToList(b, listB); merge(listA.begin(), listA.end(), listB.begin(), listB.end(), ostream_iterator<int>(cout, "\n")); } int main(int argc, char** argv) { TreeNode* rootA = new TreeNode(10, new TreeNode(5, new TreeNode(2, 0, 0), new TreeNode(6, 0, 0)), new TreeNode(15, new TreeNode(14, 0, 0), new TreeNode(20, 0, 0)) ); TreeNode* rootB = new TreeNode(40, new TreeNode(35, new TreeNode(11, new TreeNode(8, 0, 0), new TreeNode(12, 0, 0)), new TreeNode(38, 0, 0)), new TreeNode(55, new TreeNode(50, 0, 0), new TreeNode(60, 0, 0)) ); print(rootA, rootB); return 0; } ]}} - I build to trees. - Turn them into lists - merge to stdout - Anonymous July 23, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Why abrahm's code is fundamentally wrong? What he is trying to do is switch between the nodes of a tree. I think its genius

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

Abraham code is incorrect due to the fact it compares the elements present at the same level in the two trees.Due to recursion, in case Node1-value> Node2-value, Node-2 is printed , and Node1 is compared with Node2->right. However, if Node2->right=null or Node2->right->value< Node1-value, in this case Node2-right->value gets printed and control is returned to block which compared parent of Node1, (hence, Node1 value is not printed at all in the final list).

- rahul July 25, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

ahh... I think I missed the case:
N1->value >N2->value, then code traverses left tree of N2 but we missed N2 itself
e.g.
Tree1:
100
50
10
20

Tree2:
70
30
5
9
12 17

in this case it will print 5,10,12 (and will miss 9)
correct me if i am wrong.. thanks !!

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

indentation got screwed up
ahh... I think I missed the case:
N1->value >N2->value, then code traverses left tree of N2 but we missed N2 itself
e.g.
Tree1:
{
100
50
10
20
}

Tree2:
{
70
30
5
9
12 17
}

in this case it will print 5,10,12 (and will miss 9)
correct me if i am wrong.. thanks !!

- Anonymous July 25, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

The dude's post above works, but however destroys the structure of the tree.

A multi-threaded approach would work, but may be balked at due to reentrant and synchronization issues.

Here's another approach.
Make a iterator for each tree using a modified Moris-traversal algorithm.
Now it's standard merge...

- dude_2_posts_above July 24, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

my solution above doesnt wreck the structure, it uses 2(n + m) memory, which sucks. your idea of the iterator is much better, but my crappy tree didnt have one :)

- Anonymous July 24, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

In-order tree walk gives you sorted array. so you iterate over two trees together, no? Why moris traversal needed?

- Rsl July 24, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Because Moris traversal doesn't require O(m+n) extra storage?

- Jagat July 25, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

In-order tree walk gives you sorted array. so you iterate over two trees together, no? Why moris traversal needed?

- Rsl July 24, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public static void inorder(Node node1, Node node2)
{

if(node1==null || node2==null)
return;

if (node1.value < node2.value) {
inorder(node1,node2.left) ;
}
else {
inorder(node1.left,node2) ;
}

if (node1.value > node2.value ) {
// Append to Sorted list and add only if node isn't repeated....
inorder(node1,node2.right);
}
else {
// Append to Sorted list and add only if node isn't repeated....
inorder(node1.right,node2);
}

}

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

Hey Anon,

The approach is correct but 1 doubt "Where are u printing the numbers"

- rahul July 25, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@ rahul ..you can print after all the numbers are appended to the list...

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

Did you try running the code? Does it work?

- Softy July 25, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Softy

i tried the running code, it's printing all the nodes in the ascending order, except the last node, which gets missed out because of the comparison. This can be printed in the last.

Overall the concept is INORDER traversal but on two trees...so there are multiple comparison, which results in redundancy. We need to make sure not appending duplicates to the list.

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

What if one tree is empty? You are not handling that case.

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

Consider the following case.

tree 1:
   3
  2
 1

tree 2:
   6
  5
 4

Because every number in tree2 is bigger than numbers in tree1, the first number your program print will be 3 (the root node in tree1), which is incorrect.

- eviv July 28, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

The solution i can think of is, use the iterative approach the print inorder using 2 stacks for each tree, before you POP compare the top of stack of each tree and pop the lesser one.

- Softy July 30, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

void PrintMerged(struct node* root1, struct node* root2)
{
   if(root1 == NULL || root 2 == NULL)
     return;

   if (root1->data > root2->data)
   {
      if (root1->left) {
         PrintMerged(root1->left, root2);
      }
      else {
         printTreeInAscOrder(root2->left);
         print(root2->data);
      }

      if (root2->right) {
         PrintMerged(root2->right, root1);
      }
      else {
         print(root1->data);
         printTreeInAscOrder(root1->right);
      }
   }
   else {
      PrintMerged(root2, root1);
   }
}

I think this should work. This algorithm works with O(n) and no extra space. Idea is to make sure we print a node only when we know the node is in order even considering the other tree. Otherwise we move one level in first tree in the direction where the root node from the other tree is going to be in order.

- Krishan August 03, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Just had this question on my onsite interview. Best answer is to build an iterator based on a stack. Its is basically doing a depth first search.
Iterator logic:
1. from root add right node (if has one), current node and left node, repeat this step for left node.
2. when poping from stack, check if the node at top is the right node of the poped one. If so, then repeat step 1 for the left node of the node at the top of stack.
3. use the iterator to print in sorted order.

Time: O(n)
Space: O(log). By the way, you algorithm is also O(n), because thats the size of the stack used in your recursion.

public class TreeIterator {
	private Stack<TreeNode> stack = new Stack<TreeNode>();
	public TreeIterator(TreeNode root) {
		addInOrder(root);
	}
	private void addInOrder(TreeNode node) {
		if (node == null) return;
		if (node.right != null)
			stack.add(node.right);
		stack.offer(node);
		addInOrder(node.left);
	}
	
	public boolean hasNext() {
		return !stack.isEmpty();
	}
	
	public TreeNode next() {
		if (stack.isEmpty())
			return null;
		TreeNode next = stack.poll();
		if (!stack.isEmpty() && stack.peek() == next.right)
			addInOrder(next.right.left);
		return next;
	}
}

- lucas.eustaquio August 09, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Almost right, except the following change. You need to pop the next's rightChild and then call addInOrder(rightChild).

{{addInOrder(next.right.left); --> addInOrder(stack.pop());}}

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

Almost right, except the following change. You need to pop the next's rightChild and then call addInOrder(rightChild).

addInOrder(next.right.left); --> addInOrder(stack.pop());

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

@lucas, Hi lucas, could you please explain your code? How to use this on two trees. thanks

- Anonymous October 21, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

/// -- Time Complexity is O(2*max(n,m)), where n is size of root1, and m is size of root2, let me know of any errors.

void inorder(struct node * root, int min, int max)
{
	if(root == NULL) return;
	inorder(root->left, min, max);
	if((min <= root->val) && (root->val <=max))cout<<root->val<<" ";
	inorder(root->right, min, max);
}

void print(struct node * root1, struct node * root2, int min, int max)
{
	if((root1 == NULL) && (root2 == NULL)) return ;
	if(root1 != NULL && root2 == NULL) {inorder(root1, min, max); return ;}
	if(root2 != NULL && root1 == NULL) {inorder(root2, min, max); return ;}
	if(root1->val < root2->val)
	{
		print(root1->left, root2, min, root1->val);
		if((root1->val >= min) && (root1->val <= max)) cout<<root1->val<<" ";
		print(root1->right, root2, root1->val, max);
	}
	else
	{
		print(root2->left, root1, min, root2->val);
		if((root2->val >= min) && (root2->val <= max)) cout<<root2->val<<" ";
		print(root2->right, root1, root2->val, max);

	}
}

- zombie August 24, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

time: o( |n1| + |e1| ) + o(|n1| + |n2| + |e2|)
e1 and e2 are the non-leaf nodes in the tree.

space: O (|n1| * 2 + |e1| + |n2| + |e2|)

Is that correct?

rightDFSToStack(stack, root1);
dfsPrint(stack, root2);

void rightDFSToStack(stack, node) {
   if (node == null) return;
   rightDFSToStack(stack, node.right);
   stack.push(node.val);
   rightDFSToSTack(stack, node.left);
}
void dfsPrint(stack, node) {
    if (node == null) return;
    dfsPrint(stack, node.left);
    while (!stack.isEmpty() && stack.peek() < node.val) {
          print(stack.pop());
    }
    dfsPrint(stack, node.right);
}

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

Very good solution.
Only one correction
Add following in function dfsPrint(stack, node) after while loop

print(node.val);

- Anonymous October 02, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

i m not sure if any of these r the correct sol. Anybody checked for these if either of these works ?, I feel like doing recursive inorder then printing by checking whichever is the greatest

- Anonymous August 27, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

@Krishan ur code is wrong test for trees 50,100,200 and 10,250,300

- Anonymous August 27, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

@lucas.eustaquio can u explain u code

- Anonymous August 27, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

There are multiple solutions
1. Flatten both trees into two Linked list using in-order traversal. Then print the lower of the two linked list.
2. Use iterative pre-order traversal. You have better control of when to visit/delete a node.

- gavinashg September 23, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 2 vote

A solution with O(n + m) time and O(1) space would be iterating through node successors on each tree and compare them node by node. Here is the Java code bellow:

public void printAsc(TreeNode aRoot, TreeNode bRoot) {
 TreeNode nextA = minNode(aRoot);
 TreeNode nextB = minNode(bRoot);

 //Iterate node by node on each tree
 while (nextA != null || nextB != null) {
  if (nextA != null && nextB != null) {
   if (nextA.data.compareTo(nextB.data) < 0) {
     nextA = nextPrint(nextA);
    else
     nextB = nextPrint(nextB);
  }
  else if (nextA != null)
    nextA = nextPrint(nextA);
  else
    nextB = nextPrint(nextB);
 }
}

private TreeNode nextPrint(TreeNode n) {
 System.out.println(n.data);
 return successor(n);
}

private TreeNode successor(TreeNode n) {
 if (n.right != null)
  n = minNode(n.right);
 else {
  TreeNode child = n;
  TreeNode p = child.parent;
  
  while(p != null && child == p.right)   {
   child = p;
   p = child.parent;
  }

  n = p;
 }
return n;
}

private TreeNode minNode(TreeNode node) {
 while (node.left != null)
  node = node.left;

 return node;
}

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

Hi, friend. If the node has no parent, your code cannot work. So could you try one version that has no parent. And the time complexity is still O(n + m)

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

My idea
1) node* curA = Least(TreeA), curB = Least(TreeB)
2) just do the merge thing, print and increment curA = Successor(curA), if curA->val < curB->val ...

- Saurabh February 15, 2015 | 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