Jul 15 2015 • Ender Dai

Single linked list with circle

This is a classical interview question, but it is very useful in practice as well. So let’s discuss it here in detail. The problem is like this:

Given a single linked list, how to determine whether it has a circle or not?

The solution is intuitive: point two pointers, fast and slow, to the head of the list, then use them simultaneously to traverse the list. fast and slow advance m and n steps each time respectively, . If slow catches up with fast before fast reaches the end of the list, we can claim that there is a circle in the list.

It is obvious that slow will never catch up with fast if the list has no circle, i.e. . Now let’s prove that slow will finally catch up with fast if the list indeed has a circle, i.e. .

Suppose the list is composed of a linear part and a circle, the length of which are l and c respectively. Assume slow catches up with fast in s steps, then we have . Put this in another way:

Solve the equation we get

There is nothing to stop us to pick up p and q such that . So s has at least one solution, , which satisfies all the constrains below:

Therefore slow will catch up with fast in steps, though this is not necessarily the first time they meet again.

So we just proved . Now comes the follow up question:

How to find the beginning of the circle?

Let A be the head of the list, B be the beginning point of the circle, and C be the catch up point of slow and fast, then the list looks like this:

If we choose m=2 and n=1, solve the equation above we can get l+r=(p-2q)c. Let α=p-2q, then l+r=αc, l=αc-r=(α-1)c+k. Now we put a pointer p0 on A, a pointer p1 on C, then advance them 1 step every time. After k steps, p0 is (α-1)c steps away from B, but p1 reaches B already. Therefore, after (α-1)c more steps, p0 and p1 meet with each other on B.

Reference

  1. Floyd’s cycle-finding algorithm (or “tortoise and the hare algorithm”)