How can I detect that whether a singly linked-list has loop or not?? If it has loop then how to find the point of origination of the loop i.e. the node from which the loop has started.
-
Finding loops in a linked list is discussed in [Elements of Programming](http://www.amazon.com/Elements-Programming-Alexander-Stepanov/dp/032163537X), no doubt amongst many other places. – Jonathan Leffler May 20 '13 at 18:55
-
Another explanation with algorithm that can also find first cycle element: https://marcin-chwedczuk.github.io/find-cycle-start-in-singly-linked-list – csharpfolk Jun 25 '16 at 15:46
-
possible duplicate http://stackoverflow.com/questions/2936213/explain-how-finding-cycle-start-node-in-cycle-linked-list-work – RBT Nov 03 '16 at 12:54
-
1Possible duplicate of [How to detect a loop in a linked list?](http://stackoverflow.com/questions/2663115/how-to-detect-a-loop-in-a-linked-list) – G-Man Says 'Reinstate Monica' Feb 06 '17 at 02:10
-
One of my friends asked me this question and he allowed me to make it happen with O(1) complexity, and I am still stuck with that. Can anyone solve my problem ? Thanks – Mahesh Suthar Apr 21 '17 at 16:01
-
@MaheshSuthar I assume your friend meant O(1) auxiliary space, not O(1) time. It's clearly impossible in O(1) time; the accepted answer shows how to do it in O(1) space. – kaya3 Jan 18 '20 at 02:06
13 Answers
You can detect it by simply running two pointers through the list, this process is known as the tortoise and hare algorithm after the fable of the same name:
- First off, check if the list is empty (
head
isnull
). If so, no cycle exists, so stop now. - Otherwise, start the first pointer
tortoise
on the first nodehead
, and the second pointerhare
on the second nodehead.next
. - Then loop continuously until
hare
isnull
(which may be already true in a one-element list), advancingtortoise
by one andhare
by two in each iteration. The hare is guaranteed to reach the end first (if there is an end) since it started ahead and runs faster. - If there is no end (i.e., if there is a cycle), they will eventually point to the same node and you can stop, knowing you have found a node somewhere within the cycle.
Consider the following loop which starts at 3
:
head -> 1 -> 2 -> 3 -> 4 -> 5
^ |
| V
8 <- 7 <- 6
Starting tortoise
at 1 and hare
at 2, they take on the following values:
(tortoise,hare) = (1,2) (2,4) (3,6) (4,8) (5,4) (6,6)
Because they become equal at (6,6)
, and since hare
should always be beyond tortoise
in a non-looping list, it means you've discovered a cycle.
The pseudo-code will go something like this:
def hasLoop (head):
return false if head = null # Empty list has no loop.
tortoise = head # tortoise initially first element.
hare = tortoise.next # Set hare to second element.
while hare != null: # Go until hare reaches end.
return false if hare.next = null # Check enough left for hare move.
hare = hare.next.next # Move hare forward two.
tortoise = tortoise.next # Move tortoise forward one.
return true if hare = tortoise # Same means loop found.
endwhile
return false # Loop exit means no loop.
enddef
The time complexity for this algorithm is O(n)
since the number of nodes visited (by tortoise and hare) is proportional to the number of nodes.
Once you know a node within the loop, there's also 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.
head -> 1 -> 2 -> 3 -> 4 -> 5
^ |
| V
8 <- 7 <- 6
\
x (where hare and tortoise met).
This is the process to follow:
- Advance
hare
and setsize
to1
. - Then, as long as
hare
andtortoise
are different, continue to advancehare
, increasingsize
each time. This eventually gives the size of the cycle, six in this case. - At this point, if
size
is1
, that means you must already be at the start of the cycle (in a cycle of size one, there is only one possible node that can be in the cycle so it must be the first one). In this case, you simply returnhare
as the start, and skip the rest of the steps below. - Otherwise, set both
hare
andtortoise
to the first element of the list and advancehare
exactlysize
times (to the7
in this case). This gives two pointers that are different by exactly the size of the cycle. - Then, as long as
hare
andtortoise
are different, advance them both together (with the hare running at a more sedate pace, the same speed as the tortoise - I guess it's tired from its first run). Since they will remain exactlysize
elements apart from each other at all times,tortoise
will reach the start of the cycle at exactly the same time ashare
returns to the start of the cycle.
You can see that with the following walkthrough:
size tortoise hare comment
---- -------- ---- -------
6 1 1 initial state
7 advance hare by six
2 8 1/7 different, so advance both together
3 3 2/8 different, so advance both together
3/3 same, so exit loop
Hence 3
is the start point of the cycle and, since both those operations (the cycle detection and cycle start discovery) are O(n)
and performed sequentially, the whole thing taken together is also O(n)
.
If you want a more formal proof that this works, you can examine the following resources:
- a question on our sister site;
- the Wikipedia cycle detection page; or
- "The Tortoise and the Hare Algorithm" by Peter Gammie, April 17, 2016.
If you're simply after support for the method (not formal proof), you can run the following Python 3 program which evaluates its workability for a large number of sizes (how many elements in the cycle) and lead-ins (elements before the cycle start).
You'll find it always finds a point where the two pointers meet:
def nextp(p, ld, sz):
if p == ld + sz:
return ld
return p + 1
for size in range(1,1001):
for lead in range(1001):
p1 = 0
p2 = 0
while True:
p1 = nextp(p1, lead, size)
p2 = nextp(nextp(p2, lead, size), lead, size)
if p1 == p2:
print("sz = %d, ld = %d, found = %d" % (size, lead, p1))
break

- 854,327
- 234
- 1,573
- 1,953
-
Can we do better than O(n^2) for finding the start of the loop? – abc def foo bar Feb 08 '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? – Jonathan Feb 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. – paxdiablo Feb 20 '14 at 00:12
-
@Jonathan: In any case, it's a moot point. Dongliang Yu discovered a more efficient way of doing it so I've incorporated and expanded on that in this accepted answer. – paxdiablo Feb 20 '14 at 14:31
-
@paxdiablo: Yeah, I found Dongliang's solution pretty clever yesterday as well. Thanks for the clarification. – Jonathan Feb 20 '14 at 20:02
-
What harm will it do if I advance my fast pointer (B) by 3 steps instead of 2 steps? Isn't it a fast and better way? – Gaurav May 03 '14 at 14:55
-
@Gaurav, no. Consider the list `1 (2 3 4 5)` with the loop indicated by parentheses (`5` points back to `2`). The sequence there for `(a,b)` is then `(1,2) [(2,5) (3,4) (4,3) (5,2)] [(2,5) (3,4) (4,3) (5,2)] ... ad infinitum` and the pointers *never* become equal.That's because there are loop sizes that will cause `b` to always skip over `a` each time through the loop, something that's impossible if you're using `1` and `2` as the increments. – paxdiablo Jul 25 '16 at 01:52
-
@paxdiablo How to formally show that for increments of 1 and 2 the pointers will always meet irrespective of the cycle length? – user3740387 Jul 04 '17 at 20:19
-
@user3740387: Formal proof, I don't have the time (or the inclination to be honest). But let's say you have N elements (0-(N-1)). Regardless of whether N is odd or even, the advance-by-two will return to index 0 after two loops at exactly the same point the advance-by-one index wraps around once. That's because it's taken *exactly* twice as many steps. – paxdiablo Jul 05 '17 at 07:32
-
@paxdiablo: That's true when both pointers start at 0, right? But that won't be case since by the time the slow pointer reaches the loop start position 0, fast pointer can be at any position i, 0<=i<=N-1. Since the algorithm works, I'm sure after k steps from then, k%n==(i+2k)%n for some k, but is your reasoning correct? How do you guarantee that such a k will exist w/o assuming knowledge of the algorithm's correctness? – user3740387 Jul 06 '17 at 08:57
-
1@user3740387, you might want to have a look at https://math.stackexchange.com/questions/913499/proof-of-floyd-cycle-chasing-tortoise-and-hare, https://en.wikipedia.org/wiki/Cycle_detection or "The Tortoise and the Hare Algorithm" by Peter Gammie, April 17, 2016. There's a fair bit of work in understanding it (more work than I'm prepared to do at the moment) but they seem pretty definite on the matter. – paxdiablo Jul 06 '17 at 12:21
-
Suffice to say, I've actually checked this experimentally with lead-ins of 0-1000 and cycle sizes of 1-1000, and it worked every time. Now I know that my mathematician buddies will insist that's not actually proof and they'd be right. But I'm somewhat more pragmatic than that, tending to trust those more able to understand the proofs, especially with the support I see from the experimentation. – paxdiablo Jul 06 '17 at 12:24
-
-
@paxdiablo What is the time complexity of the algorithm to detect if it has a loop or not in this case? – Sisir Nov 07 '18 at 10:30
-
1@Sisir, it's O(n) since, at most, you examine each element in the list once. I'll add that to the answer. – paxdiablo Nov 07 '18 at 13:10
-
for more intuitive example , think about hour and minute needles in analog clock they run at different speeds yet they meet each other . – amarnath harish Oct 03 '19 at 14:32
The selected answer gives an O(n*n) solution to find the start node of the cycle. Here's an O(n) solution:
Once we find the slow A and fast B meet in the cycle, make one of them still and the other continue to go one step each time, to decide the perimeter of the cycle, say, P.
Then we put a node at the head and let it go P steps, and put another node at the head. We advance these two nodes both one step each time, when they first meet, it's the start point of the cycle.

- 427
- 5
- 3
-
4That'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. – paxdiablo Feb 20 '14 at 14:32
-
6That is the famous Tortoise and Hare algorithm :) http://en.wikipedia.org/wiki/Cycle_detection – jspacek Sep 07 '14 at 14:53
-
1One interviewer asked me "Why is it necessary that - when they first meet, it's the start point of the cycle.? " How to justify this statement logically? – Bhavuk Mathur Aug 12 '16 at 12:35
-
1@Bhavuk - This is justified because you are always maintaing the distance as the loopsoze constant by running those pointers with equal velocity. So once they meet again, you can definitely say the loop started and it was the start point of the loop. – Moulesh Kumar May 24 '18 at 20:50
-
for more intuitive example , think about hour and minute needles in analog clock they run at different speeds yet they meet each other – amarnath harish Oct 03 '19 at 14:32
You can use hash map also to finding whether a link list have loop or not below function uses hash map to find out whether link list have loop or not
static bool isListHaveALoopUsingHashMap(Link *headLink) {
map<Link*, int> tempMap;
Link * temp;
temp = headLink;
while (temp->next != NULL) {
if (tempMap.find(temp) == tempMap.end()) {
tempMap[temp] = 1;
} else {
return 0;
}
temp = temp->next;
}
return 1;
}
Two pointer method is best approach because time complexity is O(n) Hash Map required addition O(n) space complexity.

- 471
- 1
- 4
- 15
I read this answer in Data structure book by Narasimha Karamanchi.
We can use Floyd cycle finding algorithm, also known as tortoise and hare algorithm. In this, two pointers are used; one (say slowPtr
) is advanced by a single node, and another (say fastPtr
) is advanced by two nodes. If any loop is present in the single linked list, they both will surely meet at some point.
struct Node{
int data;
struct Node *next;
}
// program to find the begin of the loop
int detectLoopandFindBegin(struct Node *head){
struct Node *slowPtr = head, *fastPtr = head;
int loopExists = 0;
// this while loop will find if there exists a loop or not.
while(slowPtr && fastPtr && fastPtr->next){
slowPtr = slowPtr->next;
fastPtr = fastPtr->next->next;
if(slowPtr == fastPtr)
loopExists = 1;
break;
}
If there exists any loop then we point one of the pointers to the head and now advance both of them by single node. The node at which they will meet will be the start node of the loop in the single linked list.
if(loopExists){
slowPtr = head;
while(slowPtr != fastPtr){
fastPtr = fastPtr->next;
slowPtr = slowPtr->next;
}
return slowPtr;
}
return NULL;
}

- 2,912
- 2
- 17
- 32

- 345
- 4
- 9
For the most part all the previous answers are correct but here is a simplified version of the logic with visual & code (for Python 3.7)
The logic is very simple as others explained it. I'm gonna create Tortoise/slow and Hare/fast. If we move two pointers with different speed then eventually fast will meet the slow !! you can also think of this as two runners in a tack circular field. If the fast runner keeps going in circle then it will meet/pass the slow runner.
So, we will move Tortoise/slow pointer with speed 1 for each iteration while we keep incrementing or move the Hare/fast pointer with speed of 2. Once they meet we know there is a cycle. This is also known as Floyd's cycle-finding algorithm
Here is the Python code that does this (notice has_cycle method is the main part):
#!/usr/bin/env python3
class Node:
def __init__(self, data = None):
self.data = data
self.next = None
def strnode (self):
print(self.data)
class LinkedList:
def __init__(self):
self.numnodes = 0
self.head = None
def insertLast(self, data):
newnode = Node(data)
newnode.next = None
if self.head == None:
self.head = newnode
return
lnode = self.head
while lnode.next != None :
lnode = lnode.next
lnode.next = newnode # new node is now the last node
self.numnodes += 1
def has_cycle(self):
slow, fast = self.head ,self.head
while fast != None:
if fast.next != None:
fast = fast.next.next
else:
return False
slow = slow.next
if slow == fast:
print("--slow",slow.data, "fast",fast.data)
return True
return False
linkedList = LinkedList()
linkedList.insertLast("1")
linkedList.insertLast("2")
linkedList.insertLast("3")
# Create a loop for testing
linkedList.head.next.next.next = linkedList.head;
#let's check and see !
print(linkedList.has_cycle())

- 21,260
- 6
- 105
- 81
Following code will find whether there is a loop in SLL and if there, will return then starting node.
int find_loop(Node *head){
Node * slow = head;
Node * fast = head;
Node * ptr1;
Node * ptr2;
int k =1, loop_found =0, i;
if(!head) return -1;
while(slow && fast && fast->next){
slow = slow->next;
/*Moving fast pointer two steps at a time */
fast = fast->next->next;
if(slow == fast){
loop_found = 1;
break;
}
}
if(loop_found){
/* We have detected a loop */
/*Let's count the number of nodes in this loop node */
ptr1 = fast;
while(ptr1 && ptr1->next != slow){
ptr1 = ptr1->next;
k++;
}
/* Now move the other pointer by K nodes */
ptr2 = head;
ptr1 = head;
for(i=0; i<k; i++){
ptr2 = ptr2->next;
}
/* Now if we move ptr1 and ptr2 with same speed they will meet at start of loop */
while(ptr1 != ptr2){
ptr1 = ptr1->next;
ptr2 = ptr2->next;
}
return ptr1->data;
}

- 38,596
- 7
- 91
- 135

- 11
- 3
boolean hasLoop(Node *head)
{
Node *current = head;
Node *check = null;
int firstPtr = 0;
int secondPtr = 2;
do {
if (check == current) return true;
if (firstPtr >= secondPtr){
check = current;
firstPtr = 0;
secondPtr= 2*secondPtr;
}
firstPtr ++;
} while (current = current->next());
return false;
}
Another O(n) solution.

- 21,709
- 7
- 99
- 115

- 191
- 2
- 7
As I viewed the selected answer, I tried a couple of examples and found that:
If (A1,B1), (A2,B2) ... (AN, BN) are the traversals of pointers A and B
where A steps 1 element and B steps 2 elements, and, Ai and Bj are the nodes traversed by A and B, and AN=BN.
Then, the node from where the loop starts is Ak, where k = floor(N/2).

- 491
- 1
- 5
- 14
ok - I ran into this in an interview yesterday - no reference material available and I came up with a very different answer (while driving home of course...) Since the linked lists are NORMALLY (not always I admit) allocated using malloc logic then we know that the granularity of the allocations is known. On most systems this is 8 bytes - this means that the bottom 3 bits are always zeros. Consider - if we place the linked list in a class to control access and use a mask of 0x0E ored into the next address then we can use the lower 3 bits to store a break crumb Thus we can write a method that will store our last breadcrumb - say 1 or 2 - and alternate them. Our method that checks for a loop can then step through each node (using our next method) and check if the next address contains the current breadcrumb - if it does we have a loop - if it does not then we would mask the lower 3 bits and add our current breadcrumb. The breadcrumb checking algorithm would have to be single threaded as you could not run two of them at once but it would allow other threads to access the list async - with the usual caveats about adding/deleting nodes. What do you think? If others feel this is a valid solution I can write up the sample class ... Just think sometimes a fresh approach is good and am always willing to be told I have just missed the point... Thanks All Mark

- 231
- 2
- 4
Another solution
Detecting a Loop:
- create a list
- loop through the linkedlist and keep on adding the node to the list.
- If the Node is already present in the List, we have a loop.
Removal of loop:
- In the Step#2 above, while loop through the linked list we are also keep track of the previous node.
Once we detect the loop in Step#3, set previous node's next value to NULL
#code
def detect_remove_loop(head)
cur_node = head node_list = [] while cur_node.next is not None: prev_node = cur_node cur_node = cur_node.next if cur_node not in node_list: node_list.append(cur_node) else: print('Loop Detected') prev_node.next = None return print('No Loop detected')

- 8,169
- 1
- 31
- 27
Firstly, Create a Node
struct Node {
int data;
struct Node* next;
};
Initialize head pointer globally
Struct Node* head = NULL;
Insert some data in Linked List
void insert(int newdata){
Node* newNode = new Node();
newNode->data = newdata;
newNode->next = head;
head = newNode;
}
Create a function detectLoop()
void detectLoop(){
if (head == NULL || head->next == NULL){
cout<< "\nNo Lopp Found in Linked List";
}
else{
Node* slow = head;
Node* fast = head->next;
while((fast && fast->next) && fast != NULL){
if(fast == slow){
cout<<"Loop Found";
break;
}
fast = fast->next->next;
slow = slow->next;
}
if(fast->next == NULL){
cout<<"Not Found";
}
}
}
Call the function from main()
int main()
{
insert(4);
insert(3);
insert(2);
insert(1);
//Created a Loop for Testing, Comment the next line to check the unloop linkedlist
head->next->next->next->next = head->next;
detectLoop();
//If you uncomment the display function and make a loop in linked list and then run the code you will find infinite loop
//display();
}

- 2,913
- 1
- 27
- 29
-
Full program: https://github.com/iamrahman/DataStructure/blob/master/Singly_Linked_List/find_loop_in_linkedlist.cpp – Inamur Rahman Apr 23 '19 at 06:34
bool FindLoop(struct node *head)
{
struct node *current1,*current2;
current1=head;
current2=head;
while(current1!=NULL && current2!= NULL && current2->next!= NULL)
{
current1=current1->next;
current2=current2->next->next;
if(current1==current2)
{
return true;
}
}
return false;
}

- 320
- 3
- 6
A quite different method:- Reverse the linked list. While reversing if you reach the head again then there is a loop in the list, if you get NULL then there is no loop. The total time complexity is O(n)

- 403
- 1
- 3
- 10
-
1Can you reverse if there is a loop? Won't it run infinitely since you'll never reach the end to start reversing? – CodyBugstein Aug 02 '16 at 17:33
-
When you try to reverse the list add, a condition to check whether head is being re-visited. So for a->b->c->d->b will terminate as a<-b<-c<-d- – Rumu Aug 03 '16 at 19:03
-