💡 The cycle start node is found by moving pointers at equal speed from head and meeting point.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def detectCycle(head):
slow = fast = head # STEP 1
while fast and fast.next: # STEP 2-8 loop
slow = slow.next # STEP 2,4,6
fast = fast.next.next # STEP 3,5,7
if slow == fast: # STEP 8
break
else:
return None
ptr1 = head # STEP 9
ptr2 = slow # STEP 9
while ptr1 != ptr2: # STEP 10-11 loop
ptr1 = ptr1.next # STEP 10
ptr2 = ptr2.next # STEP 10
return ptr1 # STEP 11
# Example usage:
# node4 = ListNode(-4)
# node3 = ListNode(0, node4)
# node2 = ListNode(2, node3)
# node1 = ListNode(3, node2)
# node4.next = node2 # cycle
# print(detectCycle(node1).val) # Output: 2 (cycle start)
📊
Linked List Cycle II - Start of Cycle - Watch the Algorithm Execute, Step by Step
Watching the pointers move step-by-step reveals how Floyd’s algorithm detects cycles and locates their start without extra memory.
Step 1/11
·Active fill★Answer cell
advance
3
→
2
→
0
→
-4
advance
3
→
2
→
0
→
-4
advance
3
→
2
→
0
→
-4
advance
3
→
2
→
0
→
-4
advance
3
→
2
→
0
→
-4
advance
3
→
2
→
0
→
-4
compare
3
→
2
→
0
→
-4
compare
3
→
2
→
0
→
-4
advance
3
→
2
→
0
→
-4
compare
3
→
2
→
0
→
-4
compare
3
→
2
→
0
→
-4
Result: 1
Key Takeaways
✓ Floyd’s algorithm detects a cycle by moving two pointers at different speeds until they meet inside the cycle.
This meeting point inside the cycle is not obvious from code alone but is clear when watching pointers move.
✓ After detecting a cycle, resetting one pointer to head and moving both pointers at the same speed finds the cycle start.
The logic behind why moving both pointers at the same speed leads to the cycle start is easier to grasp visually.
✓ The cycle start node is the first node where the two pointers meet after the second phase of traversal.
Seeing the pointers converge on the exact node clarifies the algorithm’s correctness and final output.
Practice
(1/5)
1. Given the following code snippet for detecting a circular array loop, what is the return value when the input is nums = [2, -1, 1, 2, 2]?
easy
A. True
B. False
C. Raises an IndexError
D. Infinite loop
Solution
Step 1: Trace first iteration starting at index 0
nums[0]=2 (positive), direction is forward. slow and fast start at 0.
Step 2: Move slow and fast pointers
slow moves to index (0+2)%5=2, fast moves two steps: first to 2, then to (2+1)%5=3. Both nums[2] and nums[3] are positive, direction consistent.
Step 3: Next iteration
slow moves to (2+1)%5=3, fast moves two steps: from 3 to (3+2)%5=0, then from 0 to (0+2)%5=2. slow=3, fast=2, not equal yet.
Step 4: Next iteration
slow moves to (3+2)%5=0, fast moves two steps: from 2 to (2+1)%5=3, then from 3 to (3+2)%5=0. slow=0, fast=0, pointers meet.
Step 5: Check cycle length
Check if slow == next_index(slow): next_index(0) = 2, not equal, so cycle length > 1.
Final Answer:
Option A -> Option A
Quick Check:
Cycle detected with consistent direction and length > 1 [OK]
Hint: Pointers meet at index 0 with valid cycle -> returns True [OK]
Common Mistakes:
Confusing slow and fast pointer positions
Ignoring direction check
Mistaking single-element loop as valid
2. Consider the following Python code implementing the optimized fast-slow pointer approach for detecting a cycle in a circular array. Given the input nums = [2, -1, 1, 2, 2], what is the return value of the function circularArrayLoop(nums)?
easy
A. Raises an IndexError
B. false
C. true
D. Infinite loop
Solution
Step 1: Trace first iteration with i=0
Start at index 0, direction is positive. Moves: 0->2->3->0 forms a cycle of length >1 with consistent direction.
Step 2: Detect cycle and return true
Fast and slow pointers meet at index 0, cycle length >1, so function returns true.
For even length, returns second middle node (3) [OK]
Hint: Fast pointer moves twice as fast; slow ends at middle [OK]
Common Mistakes:
Returning first middle node for even length
Off-by-one errors in loop condition
Confusing slow and fast pointer positions
4. Identify the bug in the following Python code for checking if a number is happy. The code attempts to detect cycles using recursion but lacks proper cycle detection.
def isHappy(n: int) -> bool:
def get_next(number):
total_sum = 0
while number > 0:
digit = number % 10
total_sum += digit * digit
number //= 10
return total_sum
def helper(num):
if num == 1:
return true
return helper(get_next(num))
return helper(n)
medium
A. Missing base case for cycle detection causing infinite recursion
B. Incorrect sum of squares calculation in get_next function
C. Returning helper(get_next(num)) without checking if num is 1
D. Not initializing total_sum to zero before summing digits
Solution
Step 1: Analyze recursion base cases
The code only stops recursion if num == 1. It does not detect cycles, so for unhappy numbers it recurses infinitely.
Step 2: Identify missing cycle detection
Without tracking visited numbers or using fast-slow pointers, the recursion never terminates for cycles, causing stack overflow.
Final Answer:
Option A -> Option A
Quick Check:
Infinite recursion due to missing cycle detection base case [OK]
Hint: Check for cycle detection in recursion to avoid infinite loops [OK]
Common Mistakes:
Assuming recursion stops at cycles without explicit detection
5. Suppose the problem is modified so that after deleting N nodes, the deleted nodes can be reinserted later in the list (i.e., nodes can be reused). Which of the following changes to the algorithm is necessary to correctly handle this variant?
hard
A. Use a recursive approach to backtrack and reinsert deleted nodes at correct positions.
B. Maintain a separate data structure to store deleted nodes and reinsert them after traversal.
C. Modify the iterative approach to skip M nodes, delete N nodes, and immediately reattach deleted nodes after the next M nodes.
D. No change needed; the original iterative approach already supports node reuse.
Solution
Step 1: Understand node reuse requirement
Deleted nodes must be preserved and reinserted later, so they cannot be simply discarded by pointer reassignment.
Step 2: Evaluate algorithm changes
The original approach loses references to deleted nodes. To reuse, store deleted nodes externally and reinsert after traversal or at correct positions.