Is there any way of finding out the start of a loop in a link list using not more than two pointers? I do not want to visit every node and mark it seen and reporting the first node already been seen.Is there any other way to do this?
Is there any way of finding out the start of a loop in a link list using not more than two pointers? I do not want to visit every node and mark it seen and reporting the first node already been seen.Is there any other way to do this?
This is code to find start of loop in linked List :
public static void findStartOfLoop(Node n) {
Node fast, slow;
fast = slow = n;
do {
fast = fast.next.next;
slow = slow.next;
} while (fast != slow);
fast = n;
do {
fast = fast.next;
slow = slow.next;
}while (fast != slow);
System.out.println(" Start of Loop : " + fast.v);
}
There are two way to find the loops in a link list. 1. Use two pointer one advance one step and other advance two steps if there is loop, in some point both pointer get the same value and never reach to null. But if there is no loop pointer reaches to null in one point and both pointer never get the same value. But in this approach we can get there is a loop in the link list but we can't tell where exactly starting the loop. This is not the efficient way as well.
now:
If m is the length of the loop(nodes in the loop) that has no cyle
If n is the actual length of the loop.
x is the number of cycles slow pointer made
y is the number of cycles fast pointer made.
And K is the distance from the start of the loop to the point of meeting
Note that this point is the only piece of length in the path of both the pointers that are going to be extra after their number of cycles of the loop. So besides this k rest of what they travelled are cycles of the loop and the initial distance from the head to the start of the loop. Hence, both are travelling m+n*(numbers of cycles they made) + k distance after their cycles at which they met each other. So, we can say that:
(m + nx + k) = 2(m + n*y + k)
When you solve this mathematically you'll discover that m+k is a multiple of the length of the loop that is n. i.e. [m + k = (x-2y)*n]
So, if you maintain a distance that is a multiple of the length and move eventually you'll meet again at the start of the loop. Why? Can't they meet somewhere else? Well fast is already at k and slow is at the head, if they both travel m distance as k+m is the multiple of n, fast would be at the start of the loop. While if slow travels m distance it'll meet k as m is the distance from head to start of the loop as we originally assumed m to be.
Hence, it is mathematically proved that the distance which both the the fast and slow pointer will have to travel if set the slow pointer to head again after detecting the loop and make them both travel at the The same speed is going to be m.
public class Solution { public ListNode detectCycle(ListNode head) { if(head==null||head.next==null)return null; ListNode slow = head; ListNode fast = head; while(fast.next!=null&&fast.next.next!=null){ slow = slow.next; fast = fast.next.next; if(fast==slow){ slow=head; while(slow!=fast){ slow=slow.next; fast=fast.next; } return slow; } } return null; } }
Pythonic code solution based on @hrishikeshmishra solution
def check_loop_index(head):
if head == None or head.next == None:
return -1
slow = head.next
if head.next.next == None:
return -1
fast = head.next.next
# searching for loops exists or not
while fast and fast.next:
if slow==fast:
break
slow = slow.next
fast = fast.next.next
# checking if there is loop
if slow != fast:
return -1
# reseting the slow to head and creating index
index = 0
slow = head
# incrementing slow and fast by 1 step and incrmeenting index, if they meet
# hen thats the index of node where loop starts
while slow!=fast:
slow = slow.next
fast = fast.next
index+=1
return index