Amazon Interview Question
Developer Program EngineersCountry: India
Interview Type: Written Test
basically what Nueman Fernandez above is suggesting is to apply apply the tortoise and hare algorithm generally used to find the entry point of a rho shaped finite set function
If we number the linked list nodes from 1 to N, and 'node t' is 'z'th node. Nueman assumes that z is multiple of the numbers nodes in the loop (i.e. variable y in out proof).
To prove his point:
i.e. to prove z = C y (where c is an integer):
Let non loop length = x
Let loop length = y
The total number of nodes in the linked list N = x+y
Let say slow and fast meet after z moves.
Now slow pointer is at the node x+(z-x)%y
and the fast pointer is at x+(2z-x)%y
as both pointer have met,
x+(z-x)%y = x+(2z-x)%y
(z-x)%y = (2z-x)%y
z-x = a*y + c (a and c are integers. c<y) ----> equation 1
2z-x = b*y + c (b is an integer) -----------------> equation 2
Subtract equation 1 from equation 2
z = b*y - a*y
z = (b - a) * y
as a and b are integers, (b-a) is also an integer.
Hence z is multiple of y.
Solution sounds gud. What I figure out is , count the elements they travel before they first meet. Find the difference and that will be the speed of fast runner in the next run. In the second run they will meet at the starting point of loop. There are two different cases corresponding to even or odd size of the linked list.
Fast and slow pointers need not meet at loop starting point. you can try with a example. You can find out loop starting point by first getting the number of nodes in the loop say n and then having two pointers one at the head and other starting n nodes from head and move them at same pace. They will meet at loop start point.
Once we find the point from where the loop begins, it is fairly straight forward to find the length.
1. traverse the linked list
2. put next address in a set
3. while putting check for its presence
4. when next is found in the set take its
length
let's examine the problem with every straight solution
1. looping till the end of the linked list ( currentNode -> Next is null ), as the list has loops then we may not reach to this state
2. storing the head node and loop till ( currentNode -> Next == head node ), the cycle may not include the head node for example 1 - 2 - 3 - 4 - 3
3. one possible solution is use a integer variable without initialization which will keep a random value
every time we pass by the node we set this variable to pre-defined value, and if we pass with one node which has this variable set to our pre-defined value then we reach a loop and stop counting at this point
4. One possible solution is use hash for the nodes, whenever we pass with the node we add it to the hash, and if for any node hash[node] == true then we are in cycle and stop counting the length .. this required O(n) addition space
5. One efficient solution is we use the slow/fast pointers where fast pointer moves faster than the slow pointer and after that we will reach a moment where the fast pointer = slow pointer and in this case this is the cyclic node we can start from it and count the nodes till come back to it again, this algorithm calls "Floyed's algorithm for detecting loops, here is the algorithm
int GetLength( Node start_node )
slow_node = fast_node1 = fast_node2 = start_node
do
{
if ( slow_node == fast_node1 Or slow_node == fast_node2 )
break ;
slow_node = slow_node -> next
fast_node1 = fast_node2 -> next
fast_node2 = fast_node1 -> next
} while ( slow_node -> next != NULL );
// now the slow node is a cyclic node we can store it and count till find it again
browser_node = slow_node -> next
int cnt = 1 ;
while ( browser_node != slow_node )
cnt++
browser_node = browser_node -> next
return cnt
The following algorithm will work
1) Using start and slow pointer to detect the loop.
2) Using temporary variable pointing to the meet point. Another variable traversing through loop and comparing with the temporary variable, find the number of elements in the loop (say k).
3)Now use two pointers first pointing to start of the linked list and second pointing to the k+1 th node, move the pointers. When they meet then that will be the starting point of the loop. So the number of nodes traversed by first node + k, is the total number of nodes in the list.
Solution uses a slow and fast runner approach. The slow and fast runners will meet if the linked list is looped. Depending on if the loop start at a odd or even point in the list the list count will be the number of steps the slow runner took up minus 1 to the point it is equal to the fast runner or step behind the fast runner.
class Node {
Node next;
int data;
}
int findLength(Node head) {
if(loopedList == null)
return -1;
if(head.next == null)
return 1;
if(head.next.next == null)
return 2;
Node slow = head;
Node fast = head.next.next;
int count = 1;
while(slow != null) {
if(slow.equals(fast)){
count--;
break;
}
if(slow.next.equal(fast))
break;
slow = slow.next;
fast = fast.next.next;
count++;
}
return(count)
}
Just store head node and compare with every next nodes with head node.
It's a singly linked list, so partially looped list is not possible. e.g. '1-2-3-4-3'.
Always, head node should be linked to the last node if it's a loop.
excellent inference jk...so now you are sitting infront of the interviewer and you gave your simple solution to him and he asks a follow on question with a partially looped linked list (basically a rho shaped list which is possible and i hope you are not having any difficulty imagining that). can you please give a similar simple solution to that?
Solution 1:
If we are allowed to take extra space .. then we can use the hash_map and store all visited addresses and store it in the hash_map and increment the counter............. and then when node->next = any visited break the loop ... counter gives the length of the linked list .. o(n) time
Solution 2:
Add an additional element to the structure say add boolean visited ( instead of hashmap) we can check whether node->next == visited node break the loop return the counter
- Nueman.Fernandez December 14, 2012