package com.interview.algorithms.list; import com.interview.datastructures.list.Node; /** * Given a circular linked list, implement an algorithm which returns the node at the beginning of the loop. * * The solution * 1) Give two pointers, the fast pointer and slow pointer * 2) Move fast pointer at rate of 2 steps and slow pointer at rate of 1 step. * 3) When they collide, they will collide at LoopSize - K node after the loop beginning (or K node before the beginning) inside the loop. * K = k mod LoopSize, where k is the length of the list outside the loop. * 4) Keep fast runner as is and put slow running to list head * 5) Move fast runner and slow runner both at rate of 1, they will collide at the loop beginning. * Prove: * straight line size: N, loop size: M, fast and slow point meet at K in loop * => N + K = n * M * so: N = n * M - K * * Created_By: zouzhile * Date: 8/30/13 * Time: 7:48 PM */ public class C3_4_LoopBeginningFinder { public static Node findBegin(Node head){ if(head == null) return null; Node fast = head.next(); Node slow = head; while(fast != null && fast.next() != null &&fast != slow){ fast = fast.next().next(); slow = slow.next(); } if(fast != slow) return null; slow = slow.next(); //due to at the init stage fast is one step ahead. fast = head; while(fast != slow){ fast = fast.next(); slow = slow.next(); } return fast; } public static Node findLoopBeginning(Node head) { Node fastRunner = head; Node slowRunner = head; boolean isFreshStart = true; // first time collide, they will meet at K step before the loop beginning node. while (isFreshStart || fastRunner != slowRunner) { isFreshStart = false; fastRunner = fastRunner.next().next(); slowRunner = slowRunner.next(); } // move slow running back to head. Move 1 step for both runners, they will meet at loop beginning. slowRunner = head; isFreshStart = true; while (isFreshStart || fastRunner != slowRunner) { isFreshStart = false; fastRunner = fastRunner.next(); slowRunner = slowRunner.next(); } return fastRunner; } }