Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cracking the Coding Interview, 6th edition, 2.8

Problem Statement: Given a circular linked list, implement an algoirthm that returns the node at the beginning of the loop.

The answer key gives a more complicated solution than what I propose. What's wrong with mine?:

public static Node loopDetection(Node n1) {
    ArrayList<Node> nodeStorage = new ArrayList<Node>();

   while (n1.next != null) {
       nodeStorage.add(n1);
       if (nodeStorage.contains(n1.next)) {
           return n1;
       }
       else {
           n1 = n1.next;
       }
   }

   return null;
}
like image 753
segue_segway Avatar asked Sep 10 '15 05:09

segue_segway


People also ask

Is it worth reading Cracking the Coding Interview?

Cracking the Coding Interview gives you a great birds-eye view of the relevant data structures and algorithms, but it doesn't get deep enough into the fundamentals. When you enter a coding interview, there is a slim chance you are going to get a problem that you have seen before.

Does Cracking the Coding Interview have answers?

Not only does it give practice problems and detailed answers, but it also gives you good advice about how to approach the problems as well as what to expect.

How long does it take to crack the Coding Interview?

In a coding interview, you will be given a technical question by the interviewer. You will write the code in a real-time, collaborative editor (phone screen) or on a whiteboard (on-site), and have 30 to 45 minutes to solve the problem.


1 Answers

Your solution isO(n^2) time (each contains() in ArrayList is O(n) time) and O(n) space (for storing nodeStorage), while the "more complicated" solution is O(n) time and O(1) space.

The book offers the following solution, to whomever is interested, which is O(n) time and O(1) space:

If we move two pointers, one with speed 1 and another with speed 2, they will end up meeting if the linked list has a loop. Why? Think about two cars driving on a track—the faster car will always pass the slower one! The tricky part here is finding the start of the loop. Imagine, as an analogy, two people racing around a track, one running twice as fast as the other. If they start off at the same place, when will they next meet? They will next meet at the start of the next lap. Now, let’s suppose Fast Runner had a head start of k meters on an n step lap. When will they next meet? They will meet k meters before the start of the next lap. (Why? Fast Runner would have made k + 2(n - k) steps, including its head start, and Slow Runner would have made n - k steps. Both will be k steps before the start of the loop.) Now, going back to the problem, when Fast Runner (n2) and Slow Runner (n1) are moving around our circular linked list, n2 will have a head start on the loop when n1 enters. Specifically, it will have a head start of k, where k is the number of nodes before the loop. Since n2 has a head start of k nodes, n1 and n2 will meet k nodes before the start of the loop. So, we now know the following: 1. Head is k nodes from LoopStart (by definition). 2. MeetingPoint for n1 and n2 is k nodes from LoopStart (as shown above). Thus, if we move n1 back to Head and keep n2 at MeetingPoint, and move them both at the same pace, they will meet at LoopStart.

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;
   }
like image 184
amit Avatar answered Sep 30 '22 17:09

amit