
February 25, 2025
Detecting and Removing Cycles in Linked Lists: A Guide with Code
Why does your software loop endlessly while working with linked lists? A data structure cycle could be the cause! Cycles in linked lists may cause endless loops, memory depletion, and data handling errors. Programming efficiently and error-free requires detecting and deleting these cycles. Floyd's Cycle Detection Algorithm (Tortoise and Hare approach) is a nice solution. This blogpost will define cycles, identify them, and delete them in Python.
What is a Cycle in a Linked List?
A linked list cycles when a node's next pointer loops back to a previous node. This loop keeps the list going, producing endless traversal. Consider a list with node 4 pointing to node 2:
Due to the loop, traversing the list never ends. Detecting and eliminating such cycles ensures linked list operation stability and accuracy.
Overview of Floyd's Cycle Detection Algorithm
Floyd's Cycle Detection Algorithm (Tortoise and Hare) efficiently detects cycles in linked lists. The principle is simple: employ slow and fast pointers.
- The slow pointer moves one step at a time.
- The fast pointer moves two steps at a time.
A cycle will finally allow the fast pointer to "lap" the slow pointer and meet. Without a cycle, the fast pointer will reach the list's end.
Linear time (O(n)) and constant space (O(1)) make this approach successful.
Implementing Cycle Detection in Python
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def has_cycle(head):
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return False
# Example Usage
node1 = ListNode(1)
node2 = ListNode(2)
node3 = ListNode(3)
node4 = ListNode(4)
node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node2 # Creating a cycle
print(has_cycle(node1)) # Output: True
Start with two slow and fast pointers at the list's head. One step slow, two step fast till fast.next is None. A cycle occurs when slow and quick meet. The list is cycle-free otherwise.
Detecting and Removing the Cycle
After detecting a cycle, remove it. This requires finding the cycle's opening node. How it works:
- After detecting a cycle, reset the slow pointer to the head.
- Move slowly and fastly in steps.
- Meeting again marks the beginning of the cycle.
- Remove the cycle by setting the node's next pointer to None before the start of the cycle.
Here's the code to detect and remove the cycle:
def detect_and_remove_cycle(head):
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
break
else:
return # No cycle detected
slow = head
while slow.next != fast.next:
slow = slow.next
fast = fast.next
# Remove cycle
fast.next = None
Complexity Analysis
Time complexity: O(n)
The algorithm takes linear time since the slow and fast pointers only visit the list twice.
Space Complexity: O(1)
Due to its two pointers (slow and fast), the technique uses constant space.
Conclusion
Maintaining program integrity requires detecting and eliminating linked list cycles. Floyd's Cycle Detection Algorithm solves this problem simply yet effectively. Understanding and using this approach will provide robust and error-free linked list operations.
125 views