Removing a loop in a linked list is a crucial operation in managing linked lists, especially in scenarios where loops can lead to infinite traversals and crashes. Here’s a detailed explanation of how to detect and remove a loop from a linked list, including examples and code in various programming languages.
Understanding the Problem
A loop in a linked list occurs when a node’s next
pointer points back to a previous node, creating a cycle. Detecting and removing such loops ensures that the linked list behaves correctly and can be traversed without getting stuck.
Steps to Remove a Loop
- Detect the Loop:
- Floyd’s Cycle-Finding Algorithm (Tortoise and Hare): Use two pointers, one moving slow (one step at a time) and the other moving fast (two steps at a time). If they meet, a loop exists.
- Find the Starting Node of the Loop:
- After detecting the loop, reset one pointer to the head of the list. Move both pointers (one from the head and one from the meeting point) one step at a time until they meet again. The meeting point is the start of the loop.
- Remove the Loop:
- Traverse the loop from the starting node until you find the node that points back to the starting node and set its
next
tonull
.
Example
Consider a linked list with the following structure:
[ \text{Head} \rightarrow 1 \rightarrow 2 \rightarrow 3 \rightarrow 4 \rightarrow 5 \rightarrow \text{(back to 2)} ]
- Detect the Loop:
- Slow pointer at
1
, Fast pointer at2
. - Move fast pointer twice as fast. They meet at node
2
.
- Find the Starting Node of the Loop:
- Move one pointer from the head and one from the meeting point. They meet again at node
2
.
- Remove the Loop:
- Traverse from node
2
to find the node pointing back to node2
and set itsnext
tonull
.
Code Examples
1. Python
class ListNode:
def __init__(self, value=0, next=None):
self.value = value
self.next = next
def remove_loop(head):
if head is None:
return
slow = fast = head
# Detect loop
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
break
else:
# No loop detected
return
# Find the start of the loop
slow = head
while slow != fast:
slow = slow.next
fast = fast.next
# Remove the loop
while fast.next != slow:
fast = fast.next
fast.next = None
# Helper function to create a linked list with a loop for testing
def create_list_with_loop():
head = ListNode(1)
second = ListNode(2)
third = ListNode(3)
fourth = ListNode(4)
fifth = ListNode(5)
head.next = second
second.next = third
third.next = fourth
fourth.next = fifth
fifth.next = second # Create loop here
return head
# Example usage
head = create_list_with_loop()
remove_loop(head)
2. JavaScript
class ListNode {
constructor(value = 0, next = null) {
this.value = value;
this.next = next;
}
}
function removeLoop(head) {
if (!head) return;
let slow = head;
let fast = head;
// Detect loop
while (fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
if (slow === fast) {
break;
}
}
if (!fast || !fast.next) {
// No loop detected
return;
}
// Find the start of the loop
slow = head;
while (slow !== fast) {
slow = slow.next;
fast = fast.next;
}
// Remove the loop
while (fast.next !== slow) {
fast = fast.next;
}
fast.next = null;
}
// Helper function to create a linked list with a loop for testing
function createListWithLoop() {
const head = new ListNode(1);
const second = new ListNode(2);
const third = new ListNode(3);
const fourth = new ListNode(4);
const fifth = new ListNode(5);
head.next = second;
second.next = third;
third.next = fourth;
fourth.next = fifth;
fifth.next = second; // Create loop here
return head;
}
// Example usage
const head = createListWithLoop();
removeLoop(head);
3. Java
class ListNode {
int value;
ListNode next;
ListNode(int value) {
this.value = value;
this.next = null;
}
}
public class Main {
public static void removeLoop(ListNode head) {
if (head == null) return;
ListNode slow = head;
ListNode fast = head;
// Detect loop
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
break;
}
}
if (fast == null || fast.next == null) {
// No loop detected
return;
}
// Find the start of the loop
slow = head;
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
// Remove the loop
while (fast.next != slow) {
fast = fast.next;
}
fast.next = null;
}
// Helper function to create a linked list with a loop for testing
public static ListNode createListWithLoop() {
ListNode head = new ListNode(1);
ListNode second = new ListNode(2);
ListNode third = new ListNode(3);
ListNode fourth = new ListNode(4);
ListNode fifth = new ListNode(5);
head.next = second;
second.next = third;
third.next = fourth;
fourth.next = fifth;
fifth.next = second; // Create loop here
return head;
}
public static void main(String[] args) {
ListNode head = createListWithLoop();
removeLoop(head);
}
}
4. C++
#include <iostream>
struct ListNode {
int value;
ListNode* next;
ListNode(int val) : value(val), next(nullptr) {}
};
void removeLoop(ListNode* head) {
if (head == nullptr) return;
ListNode* slow = head;
ListNode* fast = head;
// Detect loop
while (fast != nullptr && fast->next != nullptr) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) {
break;
}
}
if (fast == nullptr || fast->next == nullptr) {
// No loop detected
return;
}
// Find the start of the loop
slow = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
// Remove the loop
while (fast->next != slow) {
fast = fast->next;
}
fast->next = nullptr;
}
// Helper function to create a linked list with a loop for testing
ListNode* createListWithLoop() {
ListNode* head = new ListNode(1);
ListNode* second = new ListNode(2);
ListNode* third = new ListNode(3);
ListNode* fourth = new ListNode(4);
ListNode* fifth = new ListNode(5);
head->next = second;
second->next = third;
third->next = fourth;
fourth->next = fifth;
fifth->next = second; // Create loop here
return head;
}
int main() {
ListNode* head = createListWithLoop();
removeLoop(head);
// Clean up memory
while (head) {
ListNode* temp = head;
head = head->next;
delete temp;
}
return 0;
}
5. C
using System;
class ListNode {
public int Value;
public ListNode Next;
public ListNode(int value) {
Value = value;
Next = null;
}
}
class Program {
public static void RemoveLoop(ListNode head) {
if (head == null) return;
ListNode slow = head;
ListNode fast = head;
// Detect loop
while (fast != null && fast.Next != null) {
slow = slow.Next;
fast = fast.Next.Next;
if (slow == fast) {
break;
}
}
if (fast == null || fast.Next == null) {
// No loop detected
return;
}
// Find the start of the loop
slow = head;
while (slow != fast) {
slow = slow.Next;
fast = fast.Next;
}
// Remove the loop
while (fast.Next != slow) {
fast
= fast.Next;
}
fast.Next = null;
}
// Helper function to create a linked list with a loop for testing
public static ListNode CreateListWithLoop() {
ListNode head = new ListNode(1);
ListNode second = new ListNode(2);
ListNode third = new ListNode(3);
ListNode fourth = new ListNode(4);
ListNode fifth = new ListNode(5);
head.Next = second;
second.Next = third;
third.Next = fourth;
fourth.Next = fifth;
fifth.Next = second; // Create loop here
return head;
}
static void Main() {
ListNode head = CreateListWithLoop();
RemoveLoop(head);
}
}
Removing a loop in a linked list involves three main steps:
- Detecting the Loop: Use Floyd’s Cycle-Finding Algorithm (Tortoise and Hare).
- Finding the Start of the Loop: Reset one pointer to the head and move both pointers one step at a time until they meet.
- Removing the Loop: Traverse the loop to find the node pointing to the start and set its
next
tonull
.