Detect Cycle in Linked List Floyd's Algorithm in DSA C++ - Time & Space Complexity
We want to understand how long it takes to check if a linked list has a cycle using Floyd's Algorithm.
How does the time grow as the linked list gets longer?
Analyze the time complexity of the following code snippet.
bool hasCycle(ListNode* head) {
ListNode* slow = head;
ListNode* fast = head;
while (fast != nullptr && fast->next != nullptr) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) {
return true;
}
}
return false;
}
This code checks if a linked list has a cycle by moving two pointers at different speeds.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that moves slow by 1 step and fast by 2 steps.
- How many times: At most, the loop runs proportional to the number of nodes before a cycle is detected or the list ends.
As the linked list length n grows, the number of steps to detect a cycle grows roughly linearly.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 steps |
| 100 | About 100 steps |
| 1000 | About 1000 steps |
Pattern observation: The steps increase roughly in direct proportion to the list size.
Time Complexity: O(n)
This means the time to detect a cycle grows linearly with the number of nodes in the list.
[X] Wrong: "Because fast moves twice as fast, the time complexity is O(n/2), so it is faster than O(n)."
[OK] Correct: We ignore constants in Big-O, so O(n/2) is still O(n). The algorithm still grows linearly with input size.
Understanding Floyd's cycle detection helps you show how to use pointers smartly to solve problems efficiently.
"What if we used only one pointer moving one step at a time? How would the time complexity change?"
Practice
Solution
Step 1: Understand Floyd's Algorithm goal
Floyd's Cycle Detection Algorithm is designed to check if a linked list contains a cycle, meaning a node points back to a previous node.Step 2: Compare with other linked list operations
Sorting, reversing, or finding the middle element are different operations and not the purpose of this algorithm.Final Answer:
To detect if there is a cycle (loop) in the linked list -> Option DQuick Check:
Cycle detection = Detect cycle [OK]
- Confusing cycle detection with sorting
- Thinking it finds the middle node
- Assuming it reverses the list
Solution
Step 1: Understand pointer initialization in Floyd's algorithm
Both slow and fast pointers start at the head node to begin traversal.Step 2: Check each option
ListNode* slow = head; ListNode* fast = head; initializes both pointers at head, which is the standard approach. Other options start pointers differently, which can cause errors or miss cycles.Final Answer:
ListNode* slow = head; ListNode* fast = head; -> Option AQuick Check:
Both pointers start at head [OK]
- Starting fast pointer at head->next causes skipping
- Initializing slow as nullptr causes null errors
- Swapping slow and fast initialization
#include <iostream>
struct Node {
int data;
Node* next;
};
bool hasCycle(Node* head) {
Node* slow = head;
Node* fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) return true;
}
return false;
}
int main() {
Node a{1, nullptr};
Node b{2, nullptr};
Node c{3, nullptr};
a.next = &b;
b.next = &c;
c.next = &b; // cycle here
bool result = hasCycle(&a);
std::cout << (result ? "Cycle detected" : "No cycle") << std::endl;
return 0;
}Solution
Step 1: Analyze linked list structure
Nodes a, b, c are linked as a->b->c, and c points back to b, creating a cycle.Step 2: Trace Floyd's algorithm behavior
Slow and fast pointers will eventually meet inside the cycle, so hasCycle returns true.Final Answer:
Cycle detected -> Option BQuick Check:
Cycle exists, so output is "Cycle detected" [OK]
- Ignoring the cycle created by c.next = &b
- Assuming no cycle because list looks linear
- Confusing output with compilation or runtime errors
bool detectCycle(Node* head) {
Node* slow = head;
Node* fast = head;
while (fast->next && fast->next->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) return true;
}
return false;
}Solution
Step 1: Check while loop condition safety
The code checks fast->next and fast->next->next but does not check if fast itself is nullptr, risking null pointer access.Step 2: Correct condition order
Proper check is to ensure fast is not nullptr before accessing fast->next to avoid runtime errors.Final Answer:
The while condition should check if fast is not nullptr before fast->next -> Option CQuick Check:
Check fast != nullptr before fast->next [OK]
- Skipping null check on fast pointer
- Starting pointers at different nodes unnecessarily
- Moving comparison outside loop causing infinite loop
Solution
Step 1: Detect cycle using Floyd's algorithm
First, detect the cycle by moving slow and fast pointers until they meet inside the cycle.Step 2: Find cycle start node
Reset one pointer to head, then move both pointers one step at a time; their meeting point is the cycle start node.Final Answer:
After detecting the cycle, reset one pointer to head and move both pointers one step at a time until they meet at the cycle start. -> Option AQuick Check:
Reset pointer + move stepwise = cycle start [OK]
- Trying to find cycle start by counting nodes
- Using extra memory like hash sets (not Floyd's method)
- Reversing list which breaks structure
Ready to prove it?
Pass the test and this pattern moves unknown
