How to Calculate the Length of a Loop in Linked Lists
What the Heck Is a Loop in a Linked List?
A loop in a linked list happens when a node's next pointer points back to an earlier node instead of null. The list never ends. It just cycles forever.
This is a bug. A serious one. It crashes programs, freezes systems, and makes interviewers hate you if you can't solve it.
You need to know two things:
- Does a loop exist? (detection)
- How long is the loop? (calculation)
This guide covers the second part. You already know how to detect loops, or you will after reading this.
Why Loop Length Matters
Knowing the loop exists isn't enough. You need the cycle length to break it. Without that number, you can't fix the list, optimize traversal, or write unit tests that actually catch this bug.
Real-world scenarios where loop length calculation saves your ass:
- Debugging memory leaks in embedded systems
- Validating data structure integrity in databases
- Passing technical interviews (this one matters more than it should)
The Floyd's Cycle Detection Method
This is the standard approach. Two pointers move at different speeds. When they meet, you've found the cycle. Then you calculate the length.
Step 1: Find the Meeting Point
Use a fast pointer (moves 2 steps) and a slow pointer (moves 1 step). If a loop exists, they will meet somewhere inside the cycle.
Node* findMeetingPoint(Node* head) {
Node* slow = head;
Node* fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) {
return slow; // Meeting point found
}
}
return NULL; // No loop
}
Step 2: Calculate the Cycle Length
Once the pointers meet, keep moving one pointer until it circles back. Count the steps.
int calculateCycleLength(Node* meetingPoint) {
Node* current = meetingPoint;
int length = 1;
while (current->next != meetingPoint) {
current = current->next;
length++;
}
return length;
}
That's it. Two steps. Meet, then count.
Step 3: Putting It Together
int getLoopLength(Node* head) {
// Step 1: Find meeting point
Node* meeting = findMeetingPoint(head);
if (!meeting) return 0; // No loop
// Step 2: Calculate length from meeting point
return calculateCycleLength(meeting);
}
The Hash Table Method
Traverse the list and store each visited node's address in a hash set. When you encounter a node that's already in the set, that's the loop start. The length is whatever you counted minus one.
int getLoopLengthHash(Node* head) {
unordered_set visited;
int count = 0;
Node* current = head;
while (current) {
if (visited.count(current)) {
// Found the loop start
break;
}
visited.insert(current);
current = current->next;
count++;
}
// Length is total visited minus the duplicate
return visited.size() > count ? visited.size() - 1 : 0;
}
This works but uses O(n) extra space. Floyd's method uses O(1) space. Pick your tradeoff.
Floyd's vs Hash Table: The Comparison
| Method | Time Complexity | Space Complexity | Drawbacks |
|---|---|---|---|
| Floyd's Cycle Detection | O(n) | O(1) | Two-pass solution |
| Hash Table | O(n) | O(n) | Uses extra memory |
Floyd's wins in most production scenarios. Less memory usage, same time complexity.
How to Start: Complete Working Example
struct Node {
int data;
Node* next;
Node(int val) : data(val), next(nullptr) {}
};
int findCycleLength(Node* head) {
if (!head || !head->next) return 0;
Node* slow = head;
Node* fast = head;
// Phase 1: Find intersection
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) break;
}
if (!fast || !fast->next) return 0; // No cycle
// Phase 2: Count the cycle
int length = 1;
Node* current = slow->next;
while (current != slow) {
current = current->next;
length++;
}
return length;
}
// Test it
int 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->next; // Creates loop at node 3
int len = findCycleLength(head);
cout << "Loop length: " << len << endl; // Outputs: 3
return 0;
}
Finding the Start Node (Bonus)
Sometimes you need the loop start node, not just the length. After finding the meeting point, reset one pointer to head and move both one step at a time. They'll meet at the loop start.
Node* findLoopStart(Node* head) {
Node* slow = head;
Node* fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) break;
}
if (!fast || !fast->next) return NULL;
// Reset slow to head, keep fast at meeting point
slow = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
return slow;
}
Common Mistakes
- Forgetting null checks — your loop will crash on acyclic lists
- Not resetting the counter — when counting from the meeting point, start at 1, not 0
- Using the wrong pointer — in the length calculation, use the meeting point, not head
- Modifying during traversal — don't alter pointers while detecting; you'll break the list
When to Use Each Method
Use Floyd's when:
- Memory is constrained
- You're writing interview code
- You need a clean, constant-space solution
Use Hash Table when:
- You also need to find the loop start node
- Memory isn't a concern
- You want simpler, more readable code
The Bottom Line
Loop detection and length calculation are fundamental skills. Floyd's algorithm gives you O(1) space and O(n) time. The hash table approach is simpler but costs memory.
Pick Floyd's for production code. Use the hash table when you need the start node and have memory to spare.
Know both. Use the right one for the situation.