Given the head of a linked list, determine the starting node of the loop if a cycle exists. A loop occurs when the last node points back to an earlier node in the list. If no loop is present, return -1.
Example:
Input:
Output: 3 Explanation: The linked list contains a loop, and the first node of the loop is 3.
Input:
Output: -1 Explanation: No loop exists in the above linked list. So the output is -1.
[Naive approach] Using Hashing - O(n) Time and O(n) Space
The idea is to start traversing the Linked List from head node and while traversing insert each node into the HashSet. If there is a loop present in the Linked List, there will be a node which will be already present in the hash set.
If there is a node which is already present in the HashSet, return the node value which represent the starting node of loop.
else, if there is no node which is already present in the HashSet , then return -1.
C++
#include<iostream>#include<unordered_set>usingnamespacestd;classNode{public:intdata;Node*next;Node(intx){data=x;next=nullptr;}};intcycleStart(Node*head){unordered_set<Node*>st;Node*currNode=head;// traverse the linked listwhile(currNode!=nullptr){// if the current node is already in the HashSet,// then this is the starting node of the loopif(st.find(currNode)!=st.end()){returncurrNode->data;}st.insert(currNode);currNode=currNode->next;}return-1;}intmain(){Node*head=newNode(1);head->next=newNode(2);head->next->next=newNode(3);head->next->next->next=newNode(4);head->next->next->next->next=newNode(5);head->next->next->next->next->next=newNode(6);head->next->next->next->next->next=head->next->next;intloopNode=cycleStart(head);if(loopNode!=-1)cout<<loopNode;elsecout<<-1;return0;}
Java
importjava.util.HashSet;classNode{intdata;Nodenext;Node(intx){data=x;next=null;}}classGfG{staticintcycleStart(Nodehead){HashSet<Node>set=newHashSet<>();NodecurrNode=head;// Traverse the linked listwhile(currNode!=null){// If current node already in set → loop startif(set.contains(currNode)){returncurrNode.data;}set.add(currNode);currNode=currNode.next;}return-1;}publicstaticvoidmain(String[]args){Nodehead=newNode(1);head.next=newNode(2);head.next.next=newNode(3);head.next.next.next=newNode(4);head.next.next.next.next=newNode(5);head.next.next.next.next.next=newNode(6);head.next.next.next.next.next=head.next.next;intloopNode=cycleStart(head);if(loopNode!=-1)System.out.println(loopNode);elseSystem.out.println(-1);}}
Python
classNode:def__init__(self,x):self.data=xself.next=NonedefcycleStart(head):visited=set()currNode=head# Traverse the linked listwhilecurrNodeisnotNone:# If current node already in set → loop startifcurrNodeinvisited:returncurrNode.datavisited.add(currNode)currNode=currNode.nextreturn-1if__name__=="__main__":head=Node(1)head.next=Node(2)head.next.next=Node(3)head.next.next.next=Node(4)head.next.next.next.next=Node(5)head.next.next.next.next.next=Node(6)head.next.next.next.next.next=head.next.nextloopNode=cycleStart(head)ifloopNode!=-1:print(loopNode)else:print(-1)
C#
usingSystem;usingSystem.Collections.Generic;classNode{publicintdata;publicNodenext;publicNode(intx){data=x;next=null;}}classGfG{staticintcycleStart(Nodehead){HashSet<Node>visited=newHashSet<Node>();NodecurrNode=head;// Traverse the linked listwhile(currNode!=null){// If current node already in set → loop startif(visited.Contains(currNode)){returncurrNode.data;}visited.Add(currNode);currNode=currNode.next;}return-1;}publicstaticvoidMain(string[]args){Nodehead=newNode(1);head.next=newNode(2);head.next.next=newNode(3);head.next.next.next=newNode(4);head.next.next.next.next=newNode(5);head.next.next.next.next.next=newNode(6);head.next.next.next.next.next=head.next.next;intloopNode=cycleStart(head);if(loopNode!=-1)Console.WriteLine(loopNode);elseConsole.WriteLine(-1);}}
JavaScript
classNode{constructor(x){this.data=x;this.next=null;}}functioncycleStart(head){letvisited=newSet();letcurrNode=head;// Traverse the linked listwhile(currNode!==null){// If current node already in set → loop startif(visited.has(currNode)){returncurrNode.data;}visited.add(currNode);currNode=currNode.next;}return-1;}// Driver Codelethead=newNode(1);head.next=newNode(2);head.next.next=newNode(3);head.next.next.next=newNode(4);head.next.next.next.next=newNode(5);head.next.next.next.next.next=newNode(6);head.next.next.next.next.next=head.next.next;letloopNode=cycleStart(head);if(loopNode!==-1)console.log(loopNode);elseconsole.log(-1);
Output
3
[Expected Approach] Using Floyd's loop detection algorithm - O(n) Time and O(1) Space
This approach can be divided into two parts:
1. Detect Loop in Linked List using Floyd’s Cycle Detection Algorithm:
This idea is to use Floyd’s Cycle-Finding Algorithm to find a loop in a linked list. It uses two pointers slow and fast, fast pointer move two steps ahead and slow will move one step ahead at a time.
Illustration:
2. Find Starting node of Loop:
After detecting that the loop is present using above algorithm, to find the starting node of loop in linked list, we will reset the slow pointer to head node and fast pointer will remain at its position. Both slow and fast pointers move one step ahead until fast not equals to slow. The meeting point will be the Starting node of loop.
#include<iostream>usingnamespacestd;classNode{public:intdata;Node*next;Node(intx){data=x;next=nullptr;}};intcycleStart(Node*head){// Initialize two pointers, slow and fastNode*slow=head;Node*fast=head;// Traverse the listwhile(fast!=nullptr&&fast->next!=nullptr){// Move slow pointer by one stepslow=slow->next;// Move fast pointer by two stepsfast=fast->next->next;// Detect loopif(slow==fast){// Move slow to head, keep fast at meeting pointslow=head;// Move both one step at a time until they meetwhile(slow!=fast){slow=slow->next;fast=fast->next;}// Return the meeting node, which// is the start of the loopreturnslow->data;}}// No loop foundreturn-1;}intmain(){Node*head=newNode(1);head->next=newNode(2);head->next->next=newNode(3);head->next->next->next=newNode(4);head->next->next->next->next=newNode(5);head->next->next->next->next->next=newNode(6);head->next->next->next->next->next=head->next->next;intloopNode=cycleStart(head);if(loopNode!=-1)cout<<loopNode;elsecout<<-1;return0;}
Java
classNode{intdata;Nodenext;Node(intx){data=x;next=null;}}classGfG{staticintcycleStart(Nodehead){Nodeslow=head;Nodefast=head;// Traverse the listwhile(fast!=null&&fast.next!=null){// Move slow pointer by one stepslow=slow.next;// Move fast pointer by two stepsfast=fast.next.next;if(slow==fast){// Move slow to head// keep fast at meeting pointslow=head;// Move both one step at a time until they meetwhile(slow!=fast){slow=slow.next;fast=fast.next;}// Return the meeting node's data,// which is the start of the loopreturnslow.data;}}return-1;}publicstaticvoidmain(String[]args){Nodehead=newNode(1);head.next=newNode(2);head.next.next=newNode(3);head.next.next.next=newNode(4);head.next.next.next.next=newNode(5);head.next.next.next.next.next=newNode(6);head.next.next.next.next.next=head.next.next;intloopNode=cycleStart(head);if(loopNode!=-1)System.out.println(loopNode);elseSystem.out.println(-1);}}
Python
classNode:def__init__(self,x):self.data=xself.next=NonedefcycleStart(head):slow=headfast=head# Traverse the listwhilefastisnotNoneandfast.nextisnotNone:# Move slow by one stepslow=slow.next# Move fast by two stepsfast=fast.next.next# Detect loopifslow==fast:# Move slow to head# keep fast at meeting pointslow=head# Move both one step at a time until they meetwhileslow!=fast:slow=slow.nextfast=fast.next# Return the meeting node's datareturnslow.datareturn-1if__name__=="__main__":head=Node(1)head.next=Node(2)head.next.next=Node(3)head.next.next.next=Node(4)head.next.next.next.next=Node(5)head.next.next.next.next.next=Node(6)head.next.next.next.next.next=head.next.nextloopNode=cycleStart(head)ifloopNode!=-1:print(loopNode)else:print(-1)
C#
usingSystem;publicclassNode{publicintdata;publicNodenext;publicNode(intx){data=x;next=null;}}classGfG{staticintcycleStart(Nodehead){Nodeslow=head;Nodefast=head;// Traverse the listwhile(fast!=null&&fast.next!=null){// Move slow pointer by one stepslow=slow.next;// Move fast pointer by two stepsfast=fast.next.next;// Detect loopif(slow==fast){// Move slow to head// keep fast at meeting pointslow=head;// Move both one step at a time until they meetwhile(slow!=fast){slow=slow.next;fast=fast.next;}// Return the meeting node's datareturnslow.data;}}return-1;}publicstaticvoidMain(string[]args){Nodehead=newNode(1);head.next=newNode(2);head.next.next=newNode(3);head.next.next.next=newNode(4);head.next.next.next.next=newNode(5);head.next.next.next.next.next=newNode(6);head.next.next.next.next.next=head.next.next;intloopNode=cycleStart(head);if(loopNode!=-1)Console.WriteLine(loopNode);elseConsole.WriteLine(-1);}}
JavaScript
classNode{constructor(x){this.data=x;this.next=null;}}functioncycleStart(head){letslow=head;letfast=head;// traverse the listwhile(fast!==null&&fast.next!==null){// move slow pointer by one stepslow=slow.next;// move fast pointer by two stepsfast=fast.next.next;// detect loopif(slow===fast){// move slow to head, keep fast at meeting pointslow=head;// move both one step at a time until they meetwhile(slow!==fast){slow=slow.next;fast=fast.next;}// return the meeting node, which is// the start of the loopreturnslow;}}// no loop foundreturnnull;}// Driver Codelethead=newNode(1);head.next=newNode(2);head.next.next=newNode(3);head.next.next.next=newNode(4);head.next.next.next.next=newNode(5);head.next.next.next.next.next=newNode(6);head.next.next.next.next.next=head.next.next;constloopNode=cycleStart(head);if(loopNode){console.log(loopNode.data);}else{console.log(-1);}