C# Program to Detect Cycle in Linked List
slow and fast, through the linked list; if they meet, a cycle exists, e.g., bool HasCycle(Node head) { Node slow = head, fast = head; while (fast != null && fast.Next != null) { slow = slow.Next; fast = fast.Next.Next; if (slow == fast) return true; } return false; }.Examples
How to Think About It
Algorithm
Code
using System; class Node { public int Value; public Node Next; public Node(int value) { Value = value; Next = null; } } class Program { static bool HasCycle(Node head) { Node slow = head, fast = head; while (fast != null && fast.Next != null) { slow = slow.Next; fast = fast.Next.Next; if (slow == fast) return true; } return false; } static void Main() { Node head = new Node(1); head.Next = new Node(2); head.Next.Next = new Node(3); head.Next.Next.Next = new Node(4); head.Next.Next.Next.Next = new Node(5); // Create cycle for testing head.Next.Next.Next.Next.Next = head.Next; // cycle back to node with value 2 Console.WriteLine(HasCycle(head) ? "Cycle detected" : "No cycle detected"); } }
Dry Run
Let's trace the linked list with nodes 1->2->3->4->5 and a cycle back to node 2 through the HasCycle method.
Initialize pointers
slow = node 1, fast = node 1
First iteration
slow moves to node 2, fast moves to node 3
Second iteration
slow moves to node 3, fast moves to node 5
Third iteration
slow moves to node 4, fast moves to node 3 (due to cycle)
Fourth iteration
slow moves to node 5, fast moves to node 5
Pointers meet
slow == fast at node 5, cycle detected
| Iteration | Slow Pointer | Fast Pointer |
|---|---|---|
| Start | 1 | 1 |
| 1 | 2 | 3 |
| 2 | 3 | 5 |
| 3 | 4 | 3 |
| 4 | 5 | 5 |
Why This Works
Step 1: Two pointers move at different speeds
The slow pointer moves one step, and the fast pointer moves two steps, so if a cycle exists, the fast pointer will eventually catch up to the slow pointer.
Step 2: Pointers meeting means cycle
When slow and fast pointers point to the same node, it means the list loops back, confirming a cycle.
Step 3: No cycle if fast pointer reaches end
If the fast pointer reaches null, it means the list ends normally without any cycle.
Alternative Approaches
using System; using System.Collections.Generic; class Node { public int Value; public Node Next; public Node(int value) { Value = value; Next = null; } } class Program { static bool HasCycle(Node head) { var visited = new HashSet<Node>(); Node current = head; while (current != null) { if (visited.Contains(current)) return true; visited.Add(current); current = current.Next; } return false; } static void Main() { Node head = new Node(1); head.Next = new Node(2); head.Next.Next = new Node(3); head.Next.Next.Next = new Node(4); head.Next.Next.Next.Next = new Node(5); head.Next.Next.Next.Next.Next = head.Next; // cycle Console.WriteLine(HasCycle(head) ? "Cycle detected" : "No cycle detected"); } }
Complexity: O(n) time, O(1) space
Time Complexity
The algorithm visits each node at most once with two pointers, so it runs in linear time O(n), where n is the number of nodes.
Space Complexity
It uses only two pointers and no extra data structures, so space complexity is constant O(1).
Which Approach is Fastest?
Floyd's algorithm is faster and uses less memory than the HashSet approach, which uses O(n) space.
| Approach | Time | Space | Best For |
|---|---|---|---|
| Floyd's Cycle Detection | O(n) | O(1) | Memory efficient, fast detection |
| HashSet Tracking | O(n) | O(n) | Simple to implement, uses extra memory |
fast or fast.Next is null before moving pointers causes runtime errors.