Detect Cycle in Linked List Floyd's Algorithm in DSA Go - 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 needed grow as the list gets bigger?
Analyze the time complexity of the following code snippet.
func hasCycle(head *ListNode) bool {
slow, fast := head, head
for fast != nil && fast.Next != nil {
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 cycle in a linked list.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The loop where slow moves one step and fast moves two steps through the list.
- How many times: At most, the loop runs once per node until pointers meet or list ends.
As the list size grows, the number of steps to detect a cycle grows roughly in a straight line.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 steps |
| 100 | About 100 steps |
| 1000 | About 1000 steps |
Pattern observation: The time grows directly with the number of nodes, so doubling nodes roughly doubles steps.
Time Complexity: O(n)
This means the time to detect a cycle grows linearly with the list size.
[X] Wrong: "Because fast moves two steps, the time complexity is O(n/2) or constant time."
[OK] Correct: Even though fast moves faster, the loop still depends on the number of nodes, so time grows linearly, not constant.
Understanding this linear time check helps you explain efficient cycle detection clearly and confidently in interviews.
"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 concept
It uses two pointers, one moving one step at a time (slow), and another moving two steps at a time (fast).Step 2: Detect cycle by pointer meeting
If the fast pointer meets the slow pointer, it means there is a cycle in the linked list.Final Answer:
Use two pointers moving at different speeds to detect a cycle -> Option CQuick Check:
Two pointers at different speeds = cycle detection [OK]
- Thinking counting nodes detects cycle
- Assuming reversing list helps detect cycle
- Using extra memory like hash map is not Floyd's method
head?Solution
Step 1: Initialize both pointers at head
Floyd's algorithm starts both slow and fast pointers at the head node.Step 2: Move pointers inside loop, not at initialization
Moving fast or slow pointer ahead at initialization can skip nodes or cause errors.Final Answer:
slow, fast := head, head -> Option AQuick Check:
Both pointers start at head [OK]
- Starting fast pointer ahead causing nil pointer errors
- Initializing slow pointer ahead skipping first node
- Setting slow pointer to nil initially
type Node struct {
val int
next *Node
}
func hasCycle(head *Node) bool {
slow, fast := head, head
for fast != nil && fast.next != nil {
slow = slow.next
fast = fast.next.next
if slow == fast {
return true
}
}
return false
}
// Linked list setup
n1 := &Node{val: 1}
n2 := &Node{val: 2}
n3 := &Node{val: 3}
n4 := &Node{val: 4}
n1.next = n2
n2.next = n3
n3.next = n4
n4.next = n2 // cycle here
fmt.Println(hasCycle(n1))Solution
Step 1: Analyze linked list structure
The list nodes are connected 1->2->3->4, and 4 points back to 2, creating a cycle.Step 2: Trace Floyd's algorithm behavior
Slow and fast pointers will eventually meet inside the cycle, so function returns true.Final Answer:
true -> Option AQuick Check:
Cycle exists, so output is true [OK]
- Assuming no cycle because list looks linear
- Expecting false without tracing pointers
- Confusing cycle detection with list length
func hasCycle(head *Node) bool {
slow, fast := head, head
for fast != nil {
slow = slow.next
fast = fast.next.next
if slow == fast {
return true
}
}
return false
}Solution
Step 1: Check loop condition safety
The loop only checks fast != nil, but fast.next could be nil causing fast.next.next to panic.Step 2: Correct loop condition
Loop should check both fast != nil and fast.next != nil to safely move fast pointer two steps.Final Answer:
The loop condition should check fast.next != nil to avoid nil pointer dereference -> Option BQuick Check:
Check fast and fast.next != nil before moving fast [OK]
- Ignoring fast.next nil check causing runtime panic
- Moving slow pointer two steps incorrectly
- Returning false too early inside loop
Solution
Step 1: Detect cycle using Floyd's algorithm
First, detect if a cycle exists by moving slow and fast pointers until they meet.Step 2: Find cycle start node
Reset one pointer to head, then move both pointers one step at a time; the node where they meet is the cycle start.Final Answer:
After detecting the cycle, reset one pointer to head and move both one step until they meet at cycle start -> Option DQuick Check:
Reset pointer + move one step = cycle start [OK]
- Trying to count nodes instead of resetting pointer
- Using extra memory instead of pointer method
- Reversing list which breaks structure
Ready to prove it?
Pass the test and this pattern moves unknown
