Detect and Remove Loop in Linked List
Last Updated :
20 Jan, 2025
Given the head of a linked list that may contain a loop. A loop means that the last node of the linked list is connected back to a node in the same list. The task is to remove the loop from the linked list (if it exists).
Example:
Input:
Output: 1 -> 3 -> 4
Explanation: The Loop is removed from the above example.
Input:
Output: 1 -> 8 -> 3 -> 4
Explanation: There is no Loop in the above example.
[Naive Approach] Detect and Remove Loop 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. Also, maintain a prev pointer which points to the previous node of the current node. 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, then update the next pointer of prev to NULL to remove the loop from the linked list.
- else, if there is no node which is already present in the HashSet , then there is no loop in the linked list.
C++
//Driver Code Starts
// C++ code to detect and remove loop in
// linked list using hashing
#include <bits/stdc++.h>
using namespace std;
struct Node {
int data;
Node *next;
Node(int x) {
data = x;
next = nullptr;
}
};
void printList(Node *curr) {
while (curr != nullptr) {
cout << curr->data << " ";
curr = curr->next;
}
cout << endl;
}
//Driver Code Ends
// Function to detect and remove loop in
// a linked list
void removeLoop(Node *head) {
// hash set to hash addresses of
// the linked list nodes
unordered_set<Node *> st;
// pointer to prev node
Node *prev = nullptr;
while (head != nullptr) {
// if node not present in the map,
// insert it in the map
if (st.find(head) == st.end()) {
st.insert(head);
prev = head;
head = head->next;
}
// if present, it is a cycle, make
// last node's next pointer NULL
else {
prev->next = nullptr;
break;
}
}
}
//Driver Code Starts
int main() {
// Create a hard-coded linked list:
// 1 -> 3 -> 4
Node *head = new Node(1);
head->next = new Node(3);
head->next->next = new Node(4);
// Create a loop
head->next->next->next = head->next;
removeLoop(head);
printList(head);
return 0;
}
//Driver Code Ends
Java
//Driver Code Starts
// Java code to detect and remove loop in linked
// list using hashing
import java.util.HashSet;
class Node {
int data;
Node next;
Node(int x) {
data = x;
next = null;
}
}
class GfG {
static void printList(Node curr) {
while (curr != null) {
System.out.print(curr.data + " ");
curr = curr.next;
}
System.out.println();
}
//Driver Code Ends
// Function to detect and remove loop in a linked list
static void removeLoop(Node head) {
// hash set to hash addresses of
// the linked list nodes
HashSet<Node> st = new HashSet<>();
// pointer to prev node
Node prev = null;
while (head != null) {
// if node not present in the map,
// insert it in the map
if (!st.contains(head)) {
st.add(head);
prev = head;
head = head.next;
}
// if present, it is a cycle, make
// last node's next pointer NULL
else {
prev.next = null;
break;
}
}
}
//Driver Code Starts
public static void main(String[] args) {
// Create a hard-coded linked list:
// 1 -> 3 -> 4
Node head = new Node(1);
head.next = new Node(3);
head.next.next = new Node(4);
// Create a loop
head.next.next.next = head.next;
removeLoop(head);
printList(head);
}
}
//Driver Code Ends
Python
#Driver Code Starts
# Python code to detect and remove loop in linked
# list using hashing
class Node:
def __init__(self, x):
self.data = x
self.next = None
def printList(curr):
# Function to print the linked list
while curr:
print(curr.data, end=' ')
curr = curr.next
print()
#Driver Code Ends
def removeLoop(head):
# Function to detect and remove loop from linked list
nodeSet = set()
prev = None
while head:
# If node is already in the set, remove the loop
if head in nodeSet:
prev.next = None
return
# Add node to the set and move forward
nodeSet.add(head)
prev = head
head = head.next
#Driver Code Starts
if __name__ == "__main__":
# Create a hard-coded linked list:
# 1 -> 3 -> 4
head = Node(1)
head.next = Node(3)
head.next.next = Node(4)
# Create a loop
head.next.next.next = head.next
removeLoop(head)
printList(head)
#Driver Code Ends
C#
//Driver Code Starts
// C# code to detect and remove loop in a
// linked list using hashing
using System;
using System.Collections.Generic;
class Node {
public int data;
public Node next;
public Node(int x) {
data = x;
next = null;
}
}
class GfG {
static void PrintList(Node curr) {
while (curr != null) {
Console.Write(curr.data + " ");
curr = curr.next;
}
}
//Driver Code Ends
// Function to detect and remove loop from linked list
static void removeLoop(Node head) {
HashSet<Node> st = new HashSet<Node>();
Node prev = null;
while (head != null) {
// If we have already seen this node in
// hash set, it means there is a cycle.
// Set the next of the previous pointer
// to null to remove the cycle.
if (st.Contains(head)) {
prev.next = null;
return;
}
// If we are seeing the node for the first time,
// insert it in hash set.
else {
st.Add(head);
prev = head;
head = head.next;
}
}
}
//Driver Code Starts
static void Main(string[] args) {
// Create a hard-coded linked list:
// 1 -> 3 -> 4
Node head = new Node(1);
head.next = new Node(3);
head.next.next = new Node(4);
// Create a loop
head.next.next.next = head.next;
removeLoop(head);
PrintList(head);
}
}
//Driver Code Ends
JavaScript
//Driver Code Starts
// JavaScript code to detect and remove loop in a
// linked list using hashing
class Node {
constructor(x) {
this.data = x;
this.next = null;
}
}
function printList(curr) {
while (curr != null) {
console.log(curr.data + " ");
curr = curr.next;
}
}
//Driver Code Ends
// Function to detect and remove loop from linked list
function removeLoop(head) {
let st = new Set();
let prev = null;
while (head != null) {
// If node is already in the set, remove the loop
if (st.has(head)) {
prev.next = null;
return;
}
// Add node to the set and move forward
st.add(head);
prev = head;
head = head.next;
}
}
//Driver Code Starts
// Create a hard-coded linked list:
// 1 -> 3 -> 4
head = new Node(1);
head.next = new Node(3);
head.next.next = new Node(4);
// Create a loop
head.next.next.next = head.next;
removeLoop(head);
printList(head);
//Driver Code Ends
Time Complexity: O(n), Where n is the number of nodes in the linked list.
Auxiliary Space: O(n), Where n is the number of nodes in the linked list(due to hashing).
[Efficient Approach] Using Floyd's Cycle Detection Algorithm - O(n) Time and O(1) Space
This approach can be divided into two parts:
- Use two pointers, slow and fast and initialize them with the head of the linked list.
- Move the fast pointer forward by two nodes and move the slow pointer forward by one node.
- If the slow and fast pointer points to the same node, loop is found.
- Else if the fast pointer reaches NULL, then no loop is found.
- Else repeat the above steps till we reach the end of the linked list or a loop is found.
2. Remove Loop in Linked List (if any):
The idea is similar to finding the starting node of Loop in a Linked List. For this, we will point 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->next is not equals to slow->next. When slow->next equals to fast->next we can easily point fast->next to NULL to remove the loop.
C++
//Driver Code Starts
// C++ program Using Floyd's Cycle Detection Algorithm
#include <bits/stdc++.h>
using namespace std;
struct Node {
int data;
Node *next;
Node(int x) {
data = x;
next = nullptr;
}
};
void printList(Node *curr) {
while (curr != nullptr) {
cout << curr->data << " ";
curr = curr->next;
}
cout << endl;
}
//Driver Code Ends
// Function to detect and remove loop in a linked list that
// may contain loop
void removeLoop(Node *head) {
// If list is empty or has only one node without loop
if (head == nullptr || head->next ==nullptr)
return;
Node *slow = head, *fast = head;
// Move slow and fast 1 and 2 steps ahead respectively.
slow = slow->next;
fast = fast->next->next;
// Search for loop using slow and fast pointers
while (fast && fast->next) {
if (slow == fast)
break;
slow = slow->next;
fast = fast->next->next;
}
// If loop exists
if (slow == fast) {
slow = head;
// this check is needed when slow and fast both meet
// at the head of the LL
if (slow == fast)
while (fast->next != slow)
fast = fast->next;
else {
while (slow->next != fast->next) {
slow = slow->next;
fast = fast->next;
}
}
// since fast->next is the looping point
fast->next = nullptr;
}
}
//Driver Code Starts
int main() {
// Create a hard-coded linked list:
// 1 -> 3 -> 4
Node *head = new Node(1);
head->next = new Node(3);
head->next->next = new Node(4);
// Create a loop
head->next->next->next = head->next;
removeLoop(head);
printList(head);
return 0;
}
//Driver Code Ends
C
//Driver Code Starts
// C program Using Floyd's Cycle Detection Algorithm
#include <stdio.h>
#include <stdlib.h>
struct Node {
int key;
struct Node *next;
};
void printList(struct Node *curr) {
while (curr != NULL) {
printf("%d ", curr->key);
curr = curr->next;
}
printf("
");
}
//Driver Code Ends
// Function to detect and remove loop in a linked list that
// may contain loop
void removeLoop(struct Node *head) {
// If list is empty or has only one node without loop
if (head == NULL || head->next == NULL)
return;
struct Node *slow = head, *fast = head;
// Move slow and fast 1 and 2 steps ahead respectively.
slow = slow->next;
fast = fast->next->next;
// Search for loop using slow and fast pointers
while (fast && fast->next) {
if (slow == fast)
break;
slow = slow->next;
fast = fast->next->next;
}
// If loop exists
if (slow == fast) {
slow = head;
// this check is needed when slow and fast both meet
// at the head of the LL
if (slow == fast)
while (fast->next != slow)
fast = fast->next;
else {
while (slow->next != fast->next) {
slow = slow->next;
fast = fast->next;
}
}
// since fast->next is the looping point
// remove loop
fast->next = NULL;
}
}
//Driver Code Starts
struct Node *createNode(int key) {
struct Node *curr =
(struct Node *)malloc(sizeof(struct Node));
curr->key = key;
curr->next = NULL;
return curr;
}
int main() {
// Create a hard-coded linked list:
// 1 -> 3 -> 4
struct Node *head = createNode(1);
head->next = createNode(3);
head->next->next = createNode(4);
// Create a loop
head->next->next->next = head->next;
removeLoop(head);
printList(head);
return 0;
}
//Driver Code Ends
Java
//Driver Code Starts
// Java program Using Floyd's Cycle Detection Algorithm
class Node {
int data;
Node next;
Node(int x) {
data = x;
next = null;
}
}
class GfG {
//Driver Code Ends
// Function that detects loop in the list
static void removeLoop(Node head) {
// If list is empty or has only one node
// without loop
if (head == null || head.next == null)
return;
Node slow = head, fast = head;
// Move slow and fast 1 and 2 steps
// ahead respectively.
slow = slow.next;
fast = fast.next.next;
// Search for loop using slow and fast pointers
while (fast != null && fast.next != null) {
if (slow == fast)
break;
slow = slow.next;
fast = fast.next.next;
}
// If loop exists
if (slow == fast) {
slow = head;
if (slow != fast) {
while (slow.next != fast.next) {
slow = slow.next;
fast = fast.next;
}
// since fast->next is the looping point
// remove loop
fast.next = null;
}
// This case is added if fast and slow
// pointer meet at first position.
else {
while(fast.next != slow) {
fast = fast.next;
}
fast.next = null;
}
}
}
//Driver Code Starts
static void printList(Node curr) {
while (curr != null) {
System.out.print(curr.data + " ");
curr = curr.next;
}
}
public static void main(String[] args) {
// Create a hard-coded linked list:
// 1 -> 3 -> 4
Node head = new Node(1);
head.next = new Node(3);
head.next.next = new Node(4);
// Create a loop
head.next.next.next = head.next;
removeLoop(head);
printList(head);
}
}
//Driver Code Ends
Python
#Driver Code Starts
# Python program Using Floyd's Cycle Detection Algorithm
class Node:
def __init__(self, x):
self.data = x
self.next = None
#Driver Code Ends
# Function to remove the loop from the linked list
def removeLoop(head):
# If the list is empty or has only one node
# without a loop
if head is None or head.next is None:
return
slow = head
fast = head
# Move slow and fast pointers; slow moves 1 step,
# fast moves 2 steps
while slow and fast and fast.next:
slow = slow.next
fast = fast.next.next
# If slow and fast meet, a loop is detected
if slow == fast:
slow = head
# Move slow and fast pointers to find the node
# where the loop starts
while slow != fast:
slow = slow.next
fast = fast.next
# Traverse the loop to find the node where the
# loop ends and remove it
while fast.next != slow:
fast = fast.next
fast.next = None
#Driver Code Starts
def printList(curr):
while curr:
print(curr.data, end=' ')
curr = curr.next
print()
if __name__ == "__main__":
# Create a linked list:
# 1 -> 3 -> 4
head = Node(1)
head.next = Node(3)
head.next.next = Node(4)
# Creating a loop
head.next.next.next = head.next
# Remove the loop from the linked list
removeLoop(head)
printList(head)
#Driver Code Ends
C#
//Driver Code Starts
// C# program Using Floyd's Cycle Detection Algorithm
class Node {
public int data;
public Node next;
public Node(int x) {
data = x;
next = null;
}
}
class GfG {
//Driver Code Ends
// Function that detects loop in the list
static void removeLoop(Node head) {
// If list is empty or has only one node
// without loop
if (head == null || head.next == null)
return;
Node slow = head, fast = head;
// Move slow and fast 1 and 2 steps
// ahead respectively.
slow = slow.next;
fast = fast.next.next;
// Search for loop using slow and fast pointers
while (fast != null && fast.next != null) {
if (slow == fast)
break;
slow = slow.next;
fast = fast.next.next;
}
// If loop exists
if (slow == fast) {
slow = head;
if (slow != fast) {
while (slow.next != fast.next) {
slow = slow.next;
fast = fast.next;
}
// since fast->next is the looping point
// remove loop
fast.next = null;
}
// This case is added if fast and slow pointer
// meet at first position.
else {
while (fast.next != slow) {
fast = fast.next;
}
fast.next = null;
}
}
}
//Driver Code Starts
static void printList(Node curr) {
while (curr != null) {
System.Console.Write(curr.data + " ");
curr = curr.next;
}
}
static void Main(string[] args) {
// Create a hard-coded linked list:
// 1 -> 3 -> 4
Node head = new Node(1);
head.next = new Node(3);
head.next.next = new Node(4);
// Create a loop
head.next.next.next = head.next;
removeLoop(head);
printList(head);
}
}
//Driver Code Ends
JavaScript
//Driver Code Starts
// JavaScript program Using Floyd's Cycle Detection Algorithm
class Node {
constructor(x) {
this.data = x;
this.next = null;
}
}
//Driver Code Ends
// Function to detect and remove loop in the linked list
function removeLoop(head) {
// If list is empty or has only one node without loop
if (head == null || head.next == null) return;
let slow = head, fast = head;
// Move slow and fast 1 and 2 steps
// ahead respectively
slow = slow.next;
fast = fast.next.next;
// Search for loop using slow and fast pointers
while (fast != null && fast.next != null) {
if (slow == fast) break;
slow = slow.next;
fast = fast.next.next;
}
// If loop exists
if (slow == fast) {
slow = head;
// If the loop starts at the head of the list
if (slow != fast) {
while (slow.next != fast.next) {
slow = slow.next;
fast = fast.next;
}
// Remove the loop
fast.next = null;
} else {
// Special case when loop starts at the head
while (fast.next != slow) {
fast = fast.next;
}
fast.next = null;
}
}
}
//Driver Code Starts
function printList(curr) {
let result = [];
while (curr != null) {
result.push(curr.data);
curr = curr.next;
}
console.log(result.join(' '));
}
// Create a hard-coded linked list:
// 1 -> 3 -> 4
let head = new Node(1);
head.next = new Node(3);
head.next.next = new Node(4);
// Create a loop
head.next.next.next = head.next;
removeLoop(head);
printList(head);
//Driver Code Ends
Time Complexity: O(n), where n is the number of nodes in the Linked List
Auxiliary Space: O(1)
For more details about the working & proof of this algorithm, Please refer to this article, How does Floyd’s Algorithm works.
Similar Reads
DSA Tutorial - Learn Data Structures and Algorithms DSA (Data Structures and Algorithms) is the study of organizing data efficiently using data structures like arrays, stacks, and trees, paired with step-by-step procedures (or algorithms) to solve problems effectively. Data structures manage how data is stored and accessed, while algorithms focus on
7 min read
Quick Sort QuickSort is a sorting algorithm based on the Divide and Conquer that picks an element as a pivot and partitions the given array around the picked pivot by placing the pivot in its correct position in the sorted array. It works on the principle of divide and conquer, breaking down the problem into s
12 min read
Merge Sort - Data Structure and Algorithms Tutorials Merge sort is a popular sorting algorithm known for its efficiency and stability. It follows the divide-and-conquer approach. It works by recursively dividing the input array into two halves, recursively sorting the two halves and finally merging them back together to obtain the sorted array. Merge
14 min read
Bubble Sort Algorithm Bubble Sort is the simplest sorting algorithm that works by repeatedly swapping the adjacent elements if they are in the wrong order. This algorithm is not suitable for large data sets as its average and worst-case time complexity are quite high.We sort the array using multiple passes. After the fir
8 min read
Data Structures Tutorial Data structures are the fundamental building blocks of computer programming. They define how data is organized, stored, and manipulated within a program. Understanding data structures is very important for developing efficient and effective algorithms. What is Data Structure?A data structure is a st
2 min read
Breadth First Search or BFS for a Graph Given a undirected graph represented by an adjacency list adj, where each adj[i] represents the list of vertices connected to vertex i. Perform a Breadth First Search (BFS) traversal starting from vertex 0, visiting vertices from left to right according to the adjacency list, and return a list conta
15+ min read
Binary Search Algorithm - Iterative and Recursive Implementation Binary Search Algorithm is a searching algorithm used in a sorted array by repeatedly dividing the search interval in half. The idea of binary search is to use the information that the array is sorted and reduce the time complexity to O(log N). Binary Search AlgorithmConditions to apply Binary Searc
15 min read
Insertion Sort Algorithm Insertion sort is a simple sorting algorithm that works by iteratively inserting each element of an unsorted list into its correct position in a sorted portion of the list. It is like sorting playing cards in your hands. You split the cards into two groups: the sorted cards and the unsorted cards. T
9 min read
Dijkstra's Algorithm to find Shortest Paths from a Source to all Given a weighted undirected graph represented as an edge list and a source vertex src, find the shortest path distances from the source vertex to all other vertices in the graph. The graph contains V vertices, numbered from 0 to V - 1.Note: The given graph does not contain any negative edge. Example
12 min read
Selection Sort Selection Sort is a comparison-based sorting algorithm. It sorts an array by repeatedly selecting the smallest (or largest) element from the unsorted portion and swapping it with the first unsorted element. This process continues until the entire array is sorted.First we find the smallest element an
8 min read