Amazon Interview Question for Software Engineer / Developers


Country: India
Interview Type: Written Test




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

q1.enqueue(head)
while(!q1.empty() && !q2.empty())
{

while(!q1.empty)
{
temp = q1.dequeue();
q3.enqueue(temp);
q2.enqueue(temp.left); // check for null
q2.enqueue(temp.right);// check for null
}
q3.enqueue("#");


while(!q2.empty)
{
temp = q2.dequeue();
q3.enqueue(temp);
q1.enqueue(temp.left);// check for null
q1.enqueue(temp.right);// check for null
}
q3.enqueue("#");
}

while(!q3.empty())
{
temp = q3.dequeue()
if(temp == "#")
sysoutprintln();
else
sysoutprint(temp);
}

- Kannan S January 25, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

small correction in m ysolution..
consider q3 as stack -
q1 and q2 as queue.

- kannan s January 25, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@kannan ...logic is correct but you are pushing head in q1 and q2 is empty initially so your code in main while loop
while(!q1.empty() && !q2.empty())

will never be executed as q2 will always be empty at starting. so you can just change it by changing && to ||

Following is the similar c++ code that i used

void reverseLevelOrder(node* root){
    if (root==NULL) return;
    else{
        queue<node*> q1,q2;
        stack <node*>s1;
        node* currNode = NULL;
        q1.push(root);//Pushing root to startwith
        while((!q1.empty()) || (!q2.empty()))
        {
            while(!q1.empty()){
                currNode= q1.front();
                q1.pop();
                if (currNode->left)q2.push(currNode->left);
                if (currNode->right)q2.push(currNode->right);
                s1.push(currNode);
            }
            s1.push(NULL);
            while(!q2.empty()){
                currNode= q2.front();
                q2.pop();
                while(!currNode){ 
                    currNode= q2.front();
                    q2.pop();
                }
                if (currNode->left)q1.push(currNode->left);
                if (currNode->right)q1.push(currNode->right);
                s1.push(currNode);
            }
            s1.push(NULL);
        }
        //now s1 has all the items to be printed
        while(!s1.empty())
        {
            currNode = s1.top();
            s1.pop();
            if (!currNode) cout<<endl;
            else cout<<currNode->data<<" ";
        }
    }
}

In case any1 needs explanation... its quite simple

Using 2 queues so that i can keep track of level..
current level's nodes are saved in one of the queues and rest are their child is saved in another and while popping from this queue to save its child on next level instead of printing it(for normal level order printing) just push into a stack so when you finally print it by popping its in reverse order.
For printing "\n" i push a NULL in the stack and when it sees a NULL in stack while printing i just print a new line for new level... hope this helps

- vik January 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Don't you think you are skipping nodes in this particular code??
Also, we can add the right node first and then the left node in both the inner while loops..

while(!q2.empty()){
                currNode= q2.front();
                q2.pop();
                while(!currNode){ 
                    currNode= q2.front();
                    q2.pop();

- Heramb February 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 2 vote

My solution is :

#include<stdio.h>
#include<stdlib.h>
struct node
{
  int data;
  struct node *right;
  struct node *left;
}*root;
struct node *createnode(int k)
{
  struct node *nwnode=malloc(sizeof(struct node));
  nwnode->data=k;
  nwnode->left=NULL;
  nwnode->right=NULL;
  return nwnode;
}
void PrintLevelNodeBottomUp(struct node *t)
{
	if(t==NULL)
	   return;
	struct node *List[20];
	int m;
	for(m=0;m<20;m++)
	   List[m]=NULL;
        int i=0;
        int j=0;
	List[i++]=t;
	struct node *pP=List[0];
	List[i++]=createnode(-1);
	while(pP!=NULL && List[j+1]!=NULL)
	{
		if(pP->right!=NULL && pP->data!=-1)
		   List[i++]=pP->right;
		if(pP->left!=NULL && pP->data!=-1)
		   List[i++]=pP->left;
		if(pP->data==-1)
		   List[i++]=createnode(-1);
		pP=List[++j];
	}
	for(m=i-1;m>=0;m--)
	{
	  if(List[m]->data==-1)
	     printf("\n");
          else
	    printf("%d ",List[m]->data);
	}
}
int main(int args,char *argv[])
{
  root=createnode(11);
  root->left=createnode(4);
  root->right=createnode(15);  
  root->left->left=createnode(3);
  root->left->right=createnode(8);
  root->left->left->left=createnode(7);
  root->left->left->left->left=createnode(1);
  root->right->left=createnode(10);
  root->right->right=createnode(16);
  root->right->right->right=createnode(14);
  root->right->left->left=createnode(5);
  root->right->right->right->right=createnode(2);
  PrintLevelNodeBottomUp(root);
}

It will take 0(n) time and O(nlogn) space , I am sure there is much better solution possible.

- Shashi January 25, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

We can use stack to make things simple and more efficient.
We start traversing the tree from root and recursively put the child of noded visited.
At last we start pop operation and print them

- Madhulika Singh January 25, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I am not sure how you will do it recursively. It will be more helpful, if you provide the code here..thanks.

- Shashi January 25, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Shashi ... you are assuming 2 things.... that there cant be -1 in tree and there are max 20 elements in tree both of which can be broken easily...however i push a NULL in queue to keep track of "\n"

- vik January 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

It is simple to code using recursion, but not efficient considering the stack space.

public static void ReverseLevelOrder(Node root)
{
    Queue queue=new Queue();
    queue.enqueue(root);
    Recursive(queue);
    System.out.println(root.value);
}
public static void Recursive(Queue queue)
{
    if(queue.isEmpty())
        return;
    Queue newqueue=new Queue();
    while(!queue.isEmpty())
    {
        TreeNode n=queue.dequeue();
        if(n.left!=null)
            newqueue.enqueue(n.left);
        if(n.right!=null)
            newqueue.enqueue(n.right);
    }
    Recursive(newqueue.clone());
    while(!newqueue.isEmpty())
        System.out.print(" "+newqueue.dequeue().value);
    System.out.println();
}

Call the first function which will call the recursive function.

- Epic January 25, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

I think this is better approach, basically u maintain two pointers currrent and nextlevel

static void printbottomtop(Node head)
        {
            int current=1, nextleval = 0;
            int index = 1;
            List<Object> nodes = new List<Object>();
            nodes.Add("#");
            nodes.Add(head);
            nodes.Add("#");
            while (true)
            {
                while (current > 0)
                {
                    Node n = (Node)nodes[index];
                    if (n.left != null)
                    {
                        nodes.Add(n.left);
                        nextleval++;
                    }
                    if (n.right != null)
                    {
                        nodes.Add(n.right);
                        nextleval++;
                    }
                    current--;
                    index--;
                }
                if (current == 0 && nextleval == 0)
                {
                    break;
                }
                else
                {
                    nodes.Add("#");
                    index = nodes.Count - 1-1;
                    current = nextleval;
                    nextleval = 0;
                }
            }
            //Now print nodes from bottom-up approach
            index = nodes.Count - 1;
            while (index>0)
            {
                if (nodes[index].ToString().Equals("#"))
                {
                    Console.WriteLine();
                }
                else
                {
                    Console.Write(((Node)nodes[index]).data.ToString()+" ");
                }
                index--;

            }

            
        }

- billu January 25, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public int findlevel() {
BinaryTreeNode prv = root;
if (root == null)
return 0;
int level = 0;
queue.add(root);
queue.add(null);
LinkedList<BinaryTreeNode> levelnodes=new LinkedList<BinaryTreeNode>();
while (!queue.isEmpty()) {
BinaryTreeNode temp = queue.remove();
if (temp != null)
{
prv = temp;
levelnodes.add(prv);
}
if (temp == null) {
level++;
LinkedList<BinaryTreeNode> l=new LinkedList<BinaryTreeNode>(levelnodes);
levelnode.put(level,l);
levelnodes.clear();
if (!queue.isEmpty())
queue.add(null);

} else {
if (temp.getLeft() != null) {
queue.add(temp.getLeft());
}
if (temp.getRight() != null)
queue.add(temp.getRight());

}

}
System.out.print("Level" + level);
queue.clear();
return level;
}

- Anonymous January 31, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Since we need to preserve the nodes while traversing, instead of using Queue for maintaining the nodes, lets use vector and take care of indexes when we change levels. I am using an "empty" node to separate out two levels.

void PrintLevelOrderList(Node * root)
{
   //if (root) do some validation

   static Node * empty =  new Node (empty); // Have some empty node, store it somewhere or create everytime

   std::vector<Node *> levelOrderList;
   levelOrderList.append(root);
   levelOrderList.append(empty);
   int index = 0; 
  
   while (true) 
   {
       Node * curr = levelOrderList[index];
       if (curr != empty)
       {
          if (curr->lc)
            levelOrderList.append(curr->lc);
          if (curr->rc)
           levelOrderList.append(curr->rc);
       }
      else
      {
          if (index == levelOrderList.size() - 1) // This is the last element
         { 
            // Hence it should terminate
             break;
          }
          else
          {
             // We have more elements, but we are done with with one level
             levelOrderList.append(empty);
          }
      } // else block
      index++;
    }// while (true) 
   
    // We should now be having a the list in the level order format. 
   // Use reverse iterators to print the nide,
   std::vector<Node *> :: reverse_iterator iter = levelOrderList.rbegin();
   while (iter != levelOrderList.rend())
   {
      if (*iter != empty)
         cout<<*iter;
      else
         cout << std::endl;
   } 
   
 }

- SR February 04, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Good ques ...
Here is my approach ...
Have a queue , stack and a vector (to keep track how many nodes in each level.
As usual push the root in the queue.
Pop the root and push its right child followed by left in the queue.
Store the root in the stack.
use the Vector to keep track of how many nodes have been explored at each level.

This is my code

void print_reverse_level_order(struct node* tree)
{
    std::queue<struct node*> Queue;
    std::stack<int> Stack;
    std::vector<int> V;

    if(tree==NULL)
        return;
    Queue.push(tree);
    V.push_back(1);
    while(!Queue.empty())
    {
        struct node* v=Queue.front();
        struct node* x;
        if(v->right!=NULL)
            x=v->right;
        else if(v->left!=NULL)
            x=v->left;
        else
        {
            x=NULL;
            Queue.pop();
            Stack.push(v->val);
            continue;
        }

        int k=0;
        while(x!=NULL && v!=x)
        {
            Stack.push(v->val);
            k++;
            if(v->right!=NULL)
                Queue.push(v->right);
            if(v->left!=NULL)
                Queue.push(v->left);
            Queue.pop();
            v=Queue.front();
        }
        V.push_back(k);
    }
    for(int i=V.size()-1;i>=0;i--)
    {
          std::cout<<"\nLevel:"<<i;
          for(int j=0;j<V[i];j++)
          {
              int d=Stack.top();
              std::cout<<" "<<d;
              Stack.pop();
          }
          std::cout<<"\n";
    }
    return;
}

- pras July 15, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Sorry did a small mistake

void print_reverse_level_order(struct node* tree)
{
    std::queue<struct node*> Queue;
    std::stack<int> Stack;
    if(tree==NULL)
        return;
    Queue.push(tree);
    while(!Queue.empty())
    {
        struct node* v=Queue.front();
        struct node* x;
        if(v->right!=NULL)
            x=v->right;
        else if(v->left!=NULL)
            x=v->left;
        else
        {
            x=NULL;
            Queue.pop();
            Stack.push(v->val);
        }
        while(v!=x  && x!=NULL)
        {
            Stack.push(v->val);
            if(v->right!=NULL)
                {Queue.push(v->right);}
            if(v->left!=NULL)
                {Queue.push(v->left);}
            Queue.pop();
            v=Queue.front();
        }
    }
    while(!Stack.empty())
    {
        std::cout<<" "<<Stack.top();
        Stack.pop();
    }
    return;

- pras July 15, 2013 | Flag
Comment hidden because of low score. Click to expand.
-1
of 1 vote

Simpler solution using queue and two stacks.
1. Doing a level order traversal using queue, also push the node into stack1 along with the level they are on.
2. Once we have reached the end, ie. queue is empty, start popping nodes from stack1 and push them into stack2.
3. When you see a change in level on the stack1, print out all elements in stack2 and then push the new node into stack2.
4. Once stack1 is empty, check if there are elements in stack2 and print them.

Any issues with this method?

- Epic January 25, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

What is the need of stack2? Stack1 alone should be enough to achieve the desired result.

- anonymous January 26, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

What should be the traversal like? left->right or right-> left?
Reason being : We can do BFS and add all the unvisited child nodes to a queue and remove the elements from queue onto a stack eventually we ll end up with traversing the node bottom to top!

- xxx January 28, 2013 | Flag


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