5 Answers
5

You can detect it by simply running two pointers through the list. Start the first pointer A on the first node and the second pointer B on the second node.

Advance the first pointer by one every time through the loop, advance the second pointer by two. If there is a loop, they will eventually point to the same node. If there's no loop, you'll eventually hit the end with the advance-by-two pointer.

Second, while A and B are not equal, continue to advance B, increasing the loopsize each time. That gives the size of the loop, six in this case. If the loopsize ends up as 1, you know that you must already be at the start of the loop, so simply return A as the start, and skip the rest of the steps below.

Third, simply set both A and B to the first element then advance B exactly loopsize times (to the 7 in this case). This gives two pointers that are different by the size of the loop.

Lastly, while A and B are not equal, you advance them together. Since they remain exactly loopsize elements apart from each other at all times, A will enter the loop at exactly the same time as B returns to the start of the loop. You can see that with the following walkthrough:

loopsize is evaluated as 6

set both A and B to 1

advance B by loopsize elements to 7

1 and 7 aren't equal so advance both

2 and 8 aren't equal so advance both

3 and 3are equal so that is your loop start

Now, since each those operations are O(n) and performed sequentially, the whole thing is O(n).

Thanks for answer.I want to know the point at which loop started. How can I do that?
–
JaguarApr 23 '12 at 6:12

3

@Jaguar, updated answer to show how you can do that.
–
paxdiabloApr 23 '12 at 6:14

Can we do better than O(n^2) for finding the start of the loop?
–
v1v3knFeb 8 '14 at 13:03

I understand advancing C by one when you don't find C within the loop after a run around it. However, is advancing B by one actually necessary? We know B is within the loop. As long as it's within the loop, it shouldn't matter at what position it is in right? It's either going to meet up with C (at the start of the loop) or meet up with itself again. It is for some running-time optimization?
–
JonathanFeb 19 '14 at 23:48

@Jonathan, the advancing B by one at the start of each cycle is to ensure it doesn't start by being equal to A. That's because A == B is the signal that C is not yet in the loop (B has run the entire loop without finding C). If we start with A == B, the cycle will exit immediately.
–
paxdiabloFeb 20 '14 at 0:12

That's actually quite clever. Working out the length of the loop (perimeter) and then advancing two pointers in sync, separated by exactly that distance until they're equal, is a better solution than the one I originally gave. +1. I've incorporated that into the accepted answer, removing my less efficient O(n^2) method in the process.
–
paxdiabloFeb 20 '14 at 14:32