Detect if a Linked List is Circular in DSA C# - Time & Space Complexity
We want to understand how long it takes to check if a linked list loops back on itself.
The question is: how does the time grow as the list gets bigger?
Analyze the time complexity of the following code snippet.
public bool IsCircular(Node head) {
if (head == null) return false;
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;
}
This code uses two pointers moving at different speeds to detect a loop in the linked list.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that moves two pointers through the list.
- How many times: At most, it runs once per node until pointers meet or list ends.
As the list grows, the number of steps grows roughly in proportion to the number of nodes.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 steps |
| 100 | About 100 steps |
| 1000 | About 1000 steps |
Pattern observation: The steps increase linearly as the list size increases.
Time Complexity: O(n)
This means the time to detect a loop grows in direct proportion to the number of nodes in the list.
[X] Wrong: "The fast pointer makes this algorithm run twice as fast, so it's O(n/2)."
[OK] Correct: We drop constants in Big-O, so O(n/2) is still O(n). The main factor is the list size, not the speed difference.
Understanding this time complexity helps you explain how efficient your loop detection is, a common question in interviews.
"What if we used only one pointer and checked visited nodes with extra memory? How would the time complexity change?"
Practice
Solution
Step 1: Understand linked list structure
A linked list is a chain of nodes where each node points to the next node.Step 2: Define circular linked list
If the last node points back to any previous node, it creates a loop, making the list circular.Final Answer:
The last node points back to one of the previous nodes, forming a loop -> Option CQuick Check:
Circular linked list = loop in nodes [OK]
- Thinking circular means sorted list
- Confusing empty list with circular
- Assuming single node list is always circular
Solution
Step 1: Identify Floyd's cycle detection logic
Two pointers move at different speeds: slow moves one step, fast moves two steps.Step 2: Check for pointer meeting
If slow and fast meet, a cycle exists; otherwise, if fast reaches null, no cycle.Final Answer:
while (fast != null && fast.Next != null) { slow = slow.Next; fast = fast.Next.Next; if (slow == fast) return true; } return false; -> Option DQuick Check:
Two-pointer cycle detection = while (fast != null && fast.Next != null) { slow = slow.Next; fast = fast.Next.Next; if (slow == fast) return true; } return false; [OK]
- Checking only one pointer for null
- Using for loop on linked list nodes
- Returning true when list is empty
class Node { public int Data; public Node Next; public Node(int d) { Data = d; Next = null; } }
Node head = new Node(1);
head.Next = new Node(2);
head.Next.Next = new Node(3);
head.Next.Next.Next = head.Next;
bool IsCircular(Node node) {
Node slow = node, fast = node;
while (fast != null && fast.Next != null) {
slow = slow.Next;
fast = fast.Next.Next;
if (slow == fast) return true;
}
return false;
}
Console.WriteLine(IsCircular(head));Solution
Step 1: Analyze linked list structure
Nodes 1 -> 2 -> 3, then 3 points back to node 2, creating a loop.Step 2: Trace Floyd's cycle detection
Slow and fast pointers will meet inside the loop, returning true.Final Answer:
true -> Option AQuick Check:
Loop detected = true [OK]
- Assuming no loop because list looks linear
- Confusing pointer equality with data equality
- Expecting false because of missing null check
bool IsCircular(Node head) {
Node slow = head, fast = head;
while (fast != null) {
slow = slow.Next;
fast = fast.Next.Next;
if (slow == fast) return true;
}
return false;
}Solution
Step 1: Review pointer movement and null checks
fast moves two steps: fast = fast.Next.Next; must check fast.Next != null to avoid null reference.Step 2: Identify missing null check
Loop condition only checks fast != null, but fast.Next could be null causing runtime error.Final Answer:
Missing check for fast.Next being null before accessing fast.Next.Next -> Option AQuick Check:
Check fast.Next != null before fast.Next.Next [OK]
- Ignoring fast.Next null check
- Moving slow pointer two steps incorrectly
- Returning false too early inside loop
public bool IsCircular(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;
}Solution
Step 1: Understand Floyd's cycle detection behavior
Fast and slow pointers move at different speeds; if any loop exists, they will meet inside it.Step 2: Consider multiple loops scenario
In a singly linked list, multiple loops cannot exist independently; any loop causes pointers to meet.Final Answer:
Floyd's cycle detection works because fast pointer will eventually meet slow pointer in any loop -> Option BQuick Check:
Any loop causes pointer meeting = true [OK]
- Thinking multiple loops can exist in singly linked list
- Believing extra memory is needed for loop detection
- Assuming method detects all loops separately
Ready to prove it?
Pass the test and this pattern moves unknown
