Amazon Interview Question for Software Engineer / Developers


Country: India
Interview Type: Written Test




Comment hidden because of low score. Click to expand.
7
of 13 vote

EDIT:
The previous algo failed for some input cases. Thanks to @ buckCherry for pointing it out. Below is the fresh algo.

Find the start of the cycle through Floyd cycle detection algorithm. The total number of nodes is the count of nodes that form cycle and count of nodes that are not part of cycle. If the list doesn't contain cycle, count of nodes that are part of cycle is zero.
1. Maintain two pointers called hare & tortoise.
2. move hare two steps & tortoise one step until either both become equal or hare reaches NULL.
3. Move tortoise to the start of the list. Move tortoise and hare step by step until their next node don't point to the same node( in case there is no cycle , hare will point to NULL. Ignore step#4 in this case). This next node is the starting node of the cycle. Meanwhile count the number of nodes that are not part of the cycle.
e.g. A->B->C->D->E->D
The number of nodes that don't form cycle is 3.

4. Count the number of nodes in the cycle. Start tortoise from the starting node of the cycle and keep on moving until it doesn't reach its initial position.
In the example explained in step#3, the number of nodes in the cycle is 2.

5. The answer is count in step#3 + count in step#4.

- Aashish June 25, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

A singly linked list can have only one loop.

- Achintya July 29, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

i dont think there will be NULL in a linked lidt having a loop.

- Anonymous September 30, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Read the question carefully. It has been clearly mentioned that
"Given a singly linked list which may or may not contain loop".

How will you come to know that the linked list is not having loop?

- Aashish October 01, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

shodnik:
When I take a linked list head->A->B->C->D->C (i.e. D loops back to C) and try to apply your algorithm, I get stuck at line #4 of your algorithm.

If I set both pointers initially at head then by line#2 I see the pointers meet at node D.
Now I keep the hare pointer at D and reset the tortoise to head as mentioned in line#3. As you've mentioned I move tortoise pointer till I reach hare at node D. Anyway this is of no use since here is not pointing NULL.
So following line#4, we hit the 'else' part. The pointer tortoise is set to head again while here is still pointing to D.
Now moving both pointers takes me into an infinite loop.

Please help me understand what's wrong is happening here!!

- buckCherry November 15, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@buckCherry, you are missing a key point. A cycle must contain at least 3 nodes. The example you are using fails because it contains a cycle of two nodes. In fact, this is not a cycle, rather it becomes a partial double linked list.
Hope you got it.

- Aashish November 17, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

shodnik:
If 3 elements/nodes were mandatory for a loop/cycle then the term 'self-loop' would have never existed!!!

I can neither agree with your requirement of at least 3 nodes for a cycle nor could understand why you're calling the above example's linked-list as partial doubly linked list.
Here is my versions of definitions and would love to see your version of the definitions.

Cycle/Loop: In a generic sense a cyclic path or loop is a path where starting from a point if you keep moving in same direction, you come back to the same point. Extending the same idea, in a linked-list if there exists any node where we can come back again by moving in one direction from that node, we call the linked list to have a loop/cycle. This definition doesn't mandate any node requirements. And using this definition, the example list Head->A->B->C->D->C is a linked list with cycle/loop since starting from C we can come back to C.
In addition, you might like to check cycle definitions in Graph theory as they are also CS data structure and we can expect certain similarity with linked-list.
Link: mathworld.wolfram.com/CycleGraph.html

Doubly Link list: If each node of a linked list stores two references - one for forward/next node and other for previous/backward node then it's a doubly linked list.
Since the example linked list I provided are neither capable of nor have stored two pointers per node they are not doubly linked list. Not sure why you call it 'PARTIAL' doubly linked list as not a single node in my example has two references.
Unfortunately, one vote down from me and am looking forward to your response

- buckCherry November 17, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@buckCherry, Apologies. The concept of Double Linked List is not correct, same for cycle concepts.
Coming back to your initial doubt, how my algo works in your example?

In step#2, hare and tortoise meet at node C. Now move tortoise to node A. So, step#3 outputs 3 nodes( A, B and C).
In step#4, fixing hare at node C and moving tortoise at node A, move hare and tortoise one step until next of both are not equal. So, move hare to node D, and tortoise to node B. Now, next of both are equal, so stop here. The total number of nodes is 4 now.
NOTE: The above algo is inspired from Floyd's Cycle detection algo.
Please let me know if you have still any doubts.

- Aashish November 17, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

shodnik:
Thanks for taking time to explain all my doubts. It helps big time.

couple of concerns though:
1) The line#4 of your algo says that tortoise is set to head while hare is fixed. So #4 should start with tortoise=Head and hare=C and with this if they move a step each time then they never meets. I didn't get why you've started your line#4 setting tortoise to A which is first element of the list and not the head!!

2)Even if you change your algorithm to indicate that in line#4 tortoise should start from first element then we get a count 4 when both of them meet at D as you've explain on Nov 17th's post. However your algorithm says 'Find sum of the counts if hare was not at NULL' and based on this the answer your algo yields is 3+4=7 which is obviously wrong!!

- buckCherry November 18, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@buckCherry,,
1) By head, i mean start/first element of the list only.

2) Sum of counts yield 4 nodes( 3 + 1 ).Step#4 outputs value of count as 1.
Explaining once again: Fix hare at node C and move tortoise to node A. Move both hare and tortoise one step. Now, hare is at node D and tortoise is at node B. Now, next of B and next of D are same node C. So, the algo stops here.
Let me know you are facing any problem.
Thank you.

- Aashish November 18, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I'll write down three cases and to me I couldn't find out what algorithm I should use for counting so that sum of the two counts becomes the answer.

1) A->B->C->D->C
     algo line #2:  they meet at C
     algo line #3:  The path tortoise make is  A-B-C
                    Considering we count number of nodes we get 3
     algo line #4:  The path tortoise make is A-B-C  (The hare's path 
                    is C-D-C)
                    Considering the node excluding start and end of
		    tortoise's move we get count 1
	            Note your algorithm says .."meanwhile keep 
		    counting number of nodes" which doesn't fit here though!!

	            So by summing 3+1=4 we get our desired answer
	            Now let's verify these counting algorithm with two 
		    more examples

2) A->B->C->D->E->D
     #2:  they meet at E  (Tortoise: A-B-C-D-E and Hare: A-C-E-E-E)
     #3:  The path tortoise make is  A-B-C-D-E
          Considering we count number of nodes we get 5
     #4:  The path tortoise make is A-B-C-D  (The hare's path 
          is E-D-E-D)
          Considering the node excluding start and end of tortoise's 
	  move we get count 2

	  So by summing 5+2=7 we get a wrong answer

3) A->B->C->A
     #2:  they meet at A  (Tortoise: A-B-C-A and Hare: A-C-B-A)
     #3:  The path tortoise make is  A-B-C-A (even thoug your algo is
          unclear here and alternate path could be A ) 
          Considering we count number of nodes we get 4 (or 
	  alternately 1)
     #4:  The path tortoise make is A-B  (alternately A)
          Considering the node excluding start and end of tortoise's 
	  move we get count 0

	  So by summing 4+0=4 (alternately 1+0=1) we get wrong 
	  answers in both ways

- buckCherry November 18, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@ shondik

Your algo (specially step#4) fails for following input :

A -> B -> C -> D -> E -> D

Step#4 would create infinite look. 


Algo for finding the number of nodes in loop is correct.  In order to find the starting node of loop ( in my example it is D) , here is my solution.
[Note : Although this also works for self-loop as well, but its efficient to detect the self-loop as a part of  finding loop in list and then count the number of nodes before self-loop nodes . ]

1.	Keep pointer ptr-1 at head of the list 
2.	Keep second pointer ptr-2 at (k+1)th  node of the list , where k = number of nodes in the loop.
3.	Check if both the pointers are pointing to same node , if yes then head is the starting point  and thus size of the loop is the size of the list.
4.	Else move both pointers ptr-1 and ptr-2 by one step until they meet at some point . Node at which both pointers meet is the start node of the loop.

Here onwards , counting the number of nodes before loop is straight forward since you now you know the start node of the loop.

- maverick November 18, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 4 vote

Traverse through the linked list. while traversing the linked list insert address(key) of each node into a hashmap.If it already exists in the hashmap then the linked list contains the loop. Maintain a counter to know the number of elements of the list while traversing..

Timecomplexity-O(n)

- Bhupathi May 13, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

ther can be duplicates.

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

Gud one Bhupathi ...:)

- Narayan June 25, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

You raised the spaace complexity. Floyd algorithm is better.

- Rachit August 07, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

drawbacks:
1) needs additional memory of complexity O(n).
2) finding address of a node might not be supported in some languages

In essence, not a very effective algorithm - one vote down.

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

you can first find if there is cycle in linklist or not(Using 2 pointer floyd theorm) in O(n) time
(i)If it is present then that node(ie. start node for cycle) will be your check point.
while counting you need to look at.


otherwise it is a normal link list

- suraj May 13, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

how cycle is detected using hare & tortouse algo?? can u please explain??

- lax July 07, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

how cycle is detected using hare & tortouse algo?? can u please explain??

- lax July 07, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

you can first find if there is cycle in linklist or not(Using 2 pointer floyd theorm) in O(n) time
(i)If it is present then that node(ie. start node for cycle) will be your check point.
while counting you need to look at.


otherwise it is a normal link list

- suraj May 13, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

first check if der is a loop wid o(n) complexity floyds theorem..
if loop is der,mark the starting node of loop wid pointr p.now tak a pointr k pointing to first node of lnkd list.traverse it until u rech p,increment countr til dat.after dis loop,point k to the next sequential node.. again run loop and increment counter untill p is rechd.. counter is the no. of nodes we wanted..

- rockstar May 13, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

This is wrong. there is no necessity that the pointers meet where there is a loop.

- Nalini Kumar July 29, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Yes Nalini. You are right, given solution is not convincing to me also.

- dachivya July 29, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@nalini can you tell me why wont the pointers meet? rockstar is correct in his approach.

- Kartik August 05, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

The pointers will surely meet and more precisely, in a way that the distance between the "pointers and the start of the loop" and the "head and the start of the loop" will be the same.

- r.sachdeva9355 August 07, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

such looping in list is solved using 2 pointers. one is ptr->next and the other is ptr->next->next. at 1 point they both meet and there your counting ends. when there is no looping you can just go to the end of the list incrementing the count.

- Anonymous May 13, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

such looping in list is solved using 2 pointers. one is ptr->next and the other is ptr->next->next. at 1 point they both meet and there your counting ends. when there is no looping you can just go to the end of the list incrementing the count.

- Anonymous May 13, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

such looping in list is solved using 2 pointers. one is ptr->next and the other is ptr->next->next. at 1 point they both meet and there your counting ends. when there is no looping you can just go till the end of the list incrementing the count.

- Anonymous May 13, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

such looping in list is solved using 2 pointers. one is ptr->next and the other is ptr->next->next. at 1 point they both meet and there your counting ends. when there is no looping you can just go till the end of the list incrementing the count.

- Anonymous May 13, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

add proper condition i.e ptr->next->next hits null if there is no looping.in such case break from the loop. otherwise two pointers will meet and thats the count.whether u start from the head r any other point

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

in the question it is specified that we may be given a link list which may or may not have a loop , and it may not start from the head.
Now consider that we were given a list which does not cointain loop (singly linked list) and we did not start form the head , then starting from the point or node given to us there might be a possibility that there were nodes behind then how can we count them when finding the no. of elements in the list.

- anonyms May 16, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

in the question it is specified that we may be given a link list which may or may not have a loop , and it may not start from the head.
Now consider that we were given a list which does not cointain loop (singly linked list) and we did not start form the head , then starting from the point or node given to us there might be a possibility that there were nodes behind then how can we count them when finding the no. of elements in the list.

- anonyms May 16, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

LinkedListNode FindBeginning(LinkedListNode head) {
LinkedListNode n1 = head;
LinkedListNode n2 = head;

// Find meeting point
while (n2.next != null) {
n1 = n1.next;
n2 = n2.next.next;
if (n1 == n2) {
break;
}
}
// Error check - there is no meeting point, and therefore no loop
if (n2.next == null) {
return null;
}
/* Move n1 to Head. Keep n2 at Meeting Point. Each are k steps
/* from the Loop Start. If they move at the same pace, they must
* meet at Loop Start. */
n1 = head;
while (n1 != n2) {
n1 = n1.next;
n2 = n2.next;
}
// Now n2 points to the start of the loop.
return n2;
}

- nagen547 May 21, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 2 vote

Here is an idea --

maintain three pointers:
a) head -- start of the given list
b) first -- jumps one step in iteration
c) second -- jumps two step in iteration

Start first and second pointers from the head and continue till both become equal (in case of loop) or second traverses the list completely and reaches the end(in case of linear list).

If the list is linear, number of nodes can be counted by traversing the list starting from head.

If the list contains a loop, notice the node where first and second becomes equal, store this new pointer tempPointer.

At this point, break the loop between tempPointer and tempPointer->next by using code below:

head2 = tempPointer->next;
tempPointer->next = null

Suppose the original list with loop was like:

head - a - b- c- d- e - f - g - h
| |
l -k - j - i

Suppose the loop is broken between f and g and null pointer is introduced:

then g becomes head2 and f->next is set to null:

head - a - b- c- d- e - f --> null
|
l - k - j - i - h - g (head2)

now we can traverse from head to null (first list)
and head2 to null (second list)

These two lists are merged at node e.

Count the number of nodes in first list -- count1
Count the number of nodes in second list -- count2

suppose count1 is greater than count2 (take whichever is greater)

then traverse first list by (count1 - count2) starting from head.
Then start traversing two lists together till you reach at merging point. Suppose you traverse M nodes together to reach merging point.

Then traverse the merged list.

The sum of nodes in both lists = number of nodes in first list + M

- Anonymous June 10, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Simply awesome , but only problem with your approach is you need to change a next pointer to null ( u need to modify the list ).

- Learner June 10, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

'Anonymous' & 'Learner'
Can any one of you please elaborate this algorithm a bit more with below two cases!
Case 1) Head ->A->B->C->D->B i.e. D loops back to B
Case 2) Head ->A->B->C->D->C i.e. D loops back to C

For "case 1" when I applied your algorithm , I see both 'first' and 'second' pointers meet at C.
By splitting I get two list i.e breaking link C -> D, we get
Head->A->B->C
head2->D->B->C

Counting both lists yield, count1=3 and count2=3.
After this, I'm lost when you say "..Then start traversing two lists together till you reach at merging point. "

Can you explain what is the merging point in this case? Also didn't get what do you mean by "Then traverse the merged list." ! Which list is the merged list here?

- buckCherry November 15, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

One vote down since it doesn't seem to work and the author didn't explain it enough to clarify all the doubts!

- buckCherry November 21, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

One vote down since it doesn't seem to work and the author didn't explain it enough to clarify all the doubts!

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

how cycle is detected using hare & tortouse algo?? can u please explain??

- venus July 07, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Mark the nodes and then count

- Munish Arya July 10, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Find the loop using floyd's algo,
then clacualte thenumber of nodes in the loop by fixing one pointer inside the loop and shifting another pointer in the loop untill bth of them become equal again, lets the number be m
now take a pointer pointing to the head and go to mth node now move the pinter to the head and the pointer pointing to the mth node step by step until the bcome equal and now you the node at which the loop starts

- ishu July 29, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Using double pointers only, will not solve this problem. There two types elements in the list; first are say, X which are not in loop and other say, Y, which belongs to loop.
let number of X are x. and number of Y are y.
And we need to calculate the x + y.

I will go with this approach:
First reverse the linked list and increment a counter, counter will be give you the value of 2x + y.
Now, using floyd cycle detection algo to find any Y. Calculate the value of y by just traversing the loop once starting from Y.
Calculate x + y, using prior equations.
Reverse again the linked list to give its original shape.
Total complexity should be O(n).

- dachivya July 29, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

What exactly does "may or may not start from the head mean" ??
We certainly cannot backtrack in a singly linked list unless its circular.
Maybe i am not clear with the question. Please explain.

- r.sachdeva9355 August 07, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

'shodnik' and 'Anonymous' have already provided solutions which I'm not fully convinced untill I receive some response against my asks to them.
In the mean time here is my solution in O(n) time and with fixed additional memory.
The only drawbacks of my algorithm is that it requires changing the structure of the list whereas both of the solutions from them does not. Note that the solution given by 'Anonymous' does a change of list structure but it can be avoided.

Anyway here is mine.

Use Robert W. Floyd's cycle detection algorithm with slight augmentation to determine if there exists any loop and if so then is there any self loop
If there is no loop
     count length of the list
     return length
else if there is any self loop
     break the self loop by pointing to null
     //i.e. a list head->A->B->B wud become head->A->B
     count length of the list
     return length
else
     invoke countNode with head of the list
end-if


countNode(Node head)
     if h==null or h->next null
          return 0;
     end-if
     Node firstNode=null;
     Node t=h->next;
     while t!= null
          Node t_dash=t;
          t=t->next;
          t_dash->next=null;
          prepend(firstNode, t_dash);
     end-while
     return length(firstNode) -1 ;
end-function

prepend(Node firstNode, Node toAdd)
     if firstNode==null
          firstNode=toAdd;
          return ;
     end-if
     Node temp=firstNode;
     firstNode=toAdd;
     firstNode->next=temp;
end-function

- buckCherry November 15, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Node slow = head;
	Node fast = head;
	while (slow != null && fast != null && slow != fast){
		slow = slow.next;
		if (fast.next== null)
			break;
		fast = fast.next.next;	
	}
	int size = 0;
	if (slow == null ||fast == null || fast.next == null){ // there is no loop
		Node temp = head;
	
		while (temp != null)
			count++;
		return count;
	}
	//now we want to find the head of the cycle
	slow = head;
	while (slow != fast){
		slow = slow.next;
		fast = fast.next;
	}
	//now fast/slow is the head of the loop
	Node current1 = head;
	Node current2 = slow.next;
	while (current1 != slow){
		size++;
		current1 = current1.next;
	}
	while (current2 != slow){
		size++;
		current2 = current2.next;
	}
	return size + 1;
}

- Anonymous June 09, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

this works fine but need to change the first while loop to do loop, or it will never into the loop since the fast = slow in the begining

- Anonymous May 02, 2014 | 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