I’m quite busy right now writing my graduation report and finishing up various projects, so this post will be written in a bit of a “freestyle” manner. Who cares, anyway?
Given a singly linked list, the problem is to check whether it contains a cycle. If it does, we need to find the starting element of the cycle and the cycle’s length .
Implicitly, this means and so on.
It is important to note that does not exist if “loops back” to the head of the linked list ; there must be some initial elements before the cycle begins (like in this case).
The Tortoise and Hare algorithm is named after its mechanism: two pointers, representing a tortoise and a hare, start from the same point. The hare moves faster than the tortoise: for every step the tortoise takes, the hare takes steps ().
Suppose both pointers start from some . After the tortoise takes steps and stops at , the hare will have taken steps and stopped at .
If the linked list does not have a cycle, the hare pointer will eventually reach NULL.
If there is a cycle, we expect the two pointers to eventually meet at some element (which must be a part of the cycle).
Suppose they meet after steps, meaning .
This occurs when and are separated by an integer multiple of the cycle length :
It is easy to see that for , the equation is always satisfied for some .
In other words: If the tortoise and the hare start at the same point, and the hare moves two steps for every one step the tortoise takes, they are guaranteed to meet after a finite number of steps.
Now, let’s find . To visualize this, with and assuming both start at , they would meet at .
At this point, the tortoise is at (which is ). We then reset the hare to the starting position (which is ). (Note: must be outside the cycle to find ).
and are separated by an integer multiple of the cycle length. However, because one belongs to the cycle and the other does not. By moving both pointers one step at a time, we maintain the distance. As soon as the hare pointer enters the cycle, it will meet the tortoise exactly at the cycle’s starting element, .
Back to our example: the hare is at , and the tortoise is at . Both then move to and , respectively. After one more step, they meet at . Thus, is the starting point of the cycle.
Finding is straightforward: since we’ve identified the starting element, we can simply move one pointer around the cycle and count the steps until it returns to .
Here is the C++ code (it doesn’t handle the case where there is no cycle; I’ll leave that as an exercise for the reader):
void detectCycle(Node * x0) {
Node * tho = x0, * rua = x0;
do {
rua = rua->next;
tho = tho->next->next;
} while(rua != tho);
// Find mu
rua = x0; // Reset one pointer to start
while(rua != tho) {
rua = rua->next;
tho = tho->next;
}
// Now rua (or tho) is mu
// Find lambda
int lambda = 0;
do {
lambda++;
tho = tho->next;
} while(tho != rua);
}