You can detect it by simply running two pointers through the list.
Start the first pointer p1 on the first node and the second pointer p2 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.
Consider the following loop:
head -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 ^ | | | +------------------------+
Starting A at 1 and B at 2, they take on the following values:
p1 p2 = = 1 2 2 4 3 6 4 8 5 4 6 6
Because they’re equal, and P2 should always be beyond
p1 in a non-looping list (because it’s advancing by two as opposed to the advance-by-one behavior of
p1), it means you’ve discovered a loop.
The pseudo-code will go something like this:
- Start with hn(Head Node )of the linked list
- If hn==null; return false; //empty list
- if hn.next!=null
- p1=hn; p2=hn;
- While p2!=null loop
- p1=p1.next//Advancing p1 by 1
- if p2.next!=null
- p2=p2.next.next//Advancing p2 by 2
- else return false
- if p1==p2
- return true// Loop was found
- return false// till now no loop was found
Once you know a node within the loop, there’s an
O(n) guaranteed method to find the start of the loop.
Let’s return to the original position after you’ve found an element somewhere in the loop but you’re not sure where the start of the loop is.
p1,p2 (this is where p1 and p2 | first met). v head -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 ^ | | | +------------------------+
This is the process to follow:
- First, advance
p2and set the
- Second, while
p2are not equal, continue to advance
p2, increasing the
loopsizeeach time. That gives the size of the loop, six in this case.
loopsizeends up as
1, you know that you must already be at the start of the loop, so simply return
Aas the start, and skip the rest of the steps below.
- Third, simply set both
p2to the first element then advance
loopsizetimes (to the
7in this case). This gives two pointers that are different by the size of the loop.
- Lastly, while
p2are not equal, you advance them together. Since they remain exactly
loopsizeelements apart from each other at all times,
p1will enter the loop at exactly the same time as
p2returns to the start of the loop. You can see that with the following walk through:
loopsizeis evaluated as
- set both
7aren’t equal so advance both
8aren’t equal so advance both
3are equal so that is your loop start
Now, since each those operations are
O(n) and performed sequentially, the whole thing is
Algorithm Name: Floyd–Warshall algorithm