Detect Cycle in Linked List using Floyd's Algorithm
📖 Scenario: Imagine you are working on a system that manages a chain of tasks linked together. Sometimes, due to errors, a task might link back to an earlier task, creating a loop. This loop can cause the system to get stuck. You need to detect if such a loop exists in the chain.
🎯 Goal: You will build a linked list and use Floyd's Cycle Detection Algorithm (also called the tortoise and hare algorithm) to check if the linked list contains a cycle.
📋 What You'll Learn
Create a linked list with nodes containing integer values
Add a configuration variable to create a cycle in the linked list
Implement Floyd's Cycle Detection Algorithm to detect if a cycle exists
Print true if a cycle is detected, otherwise false
💡 Why This Matters
🌍 Real World
Cycle detection is important in systems like task schedulers, network routing, and memory management to avoid infinite loops and crashes.
💼 Career
Understanding linked lists and cycle detection algorithms is essential for software engineers working on low-level data structures, debugging, and optimizing code.
Progress0 / 4 steps
1
Create a linked list with nodes 1 -> 2 -> 3 -> 4 -> 5 -> null
Create a struct called Node with fields value: i32 and next: Option>. Then create a linked list with nodes containing values 1, 2, 3, 4, and 5 linked in order.
DSA Rust
Hint
Start by defining the Node struct with value and next. Then create nodes from 5 up to 1, linking each node to the next.
2
Add a boolean variable create_cycle to control if the list has a cycle
Add a boolean variable called create_cycle and set it to true. This variable will be used later to decide if the linked list should have a cycle.
DSA Rust
Hint
Just add let create_cycle = true; inside the main function.
3
Implement Floyd's Cycle Detection Algorithm to detect a cycle
Implement a function called has_cycle that takes a reference to head: &Node and returns bool. Use two pointers called slow and fast to traverse the linked list. Move slow by one step and fast by two steps. If they meet, return true. If fast reaches the end, return false. Call has_cycle(&head) inside main.
DSA Rust
Hint
Use Option<&Node> for slow and fast. Move slow by one step and fast by two steps using as_deref(). If they meet, return true. Otherwise, return false.
4
Print true if cycle exists, otherwise false
Print the value of cycle_exists using println!("{}", cycle_exists) inside the main function.
DSA Rust
Hint
Use println!("{}", cycle_exists); to print the result.
Practice
(1/5)
1. What is the main idea behind Floyd's Cycle Detection Algorithm in a linked list?
easy
A. Use two pointers moving at different speeds to detect a cycle
B. Count the number of nodes and check if it exceeds a limit
C. Reverse the linked list and check if it matches the original
D. Use a hash set to store visited nodes and check for repeats
Solution
Step 1: Understand Floyd's algorithm concept
It uses two pointers, one moving faster (fast) and one slower (slow) through the list.
Step 2: Detect cycle by pointer meeting
If the fast pointer meets the slow pointer, a cycle exists; otherwise, no cycle.
Final Answer:
Use two pointers moving at different speeds to detect a cycle -> Option A
Quick Check:
Two pointers at different speeds = cycle detection [OK]
Hint: Two pointers at different speeds detect cycle fast [OK]
Common Mistakes:
Thinking counting nodes detects cycle
Assuming reversing list helps detect cycle
Using extra memory instead of pointers
2. Which Rust code snippet correctly initializes the slow and fast pointers for Floyd's cycle detection in a linked list named head?
easy
A. let mut slow = head.as_ref(); let mut fast = head.as_ref();
B. let mut slow = head.clone(); let mut fast = head.clone();
C. let mut slow = &head.next; let mut fast = &head.next.next;
D. let mut slow = &head; let mut fast = &head.next;
Solution
Step 1: Initialize both pointers at head
Floyd's algorithm starts both slow and fast pointers at the head node.
Step 2: Correct Rust reference usage
Using head.as_ref() for both slow and fast is correct; fast moves faster later.
Final Answer:
let mut slow = head.as_ref(); let mut fast = head.as_ref(); -> Option A
Quick Check:
Both pointers start at head [OK]
Hint: Start both pointers at head node [OK]
Common Mistakes:
Starting fast pointer at head.next before loop
Cloning nodes unnecessarily
Using wrong references causing borrow errors
3. What will be the output of the following Rust code snippet detecting a cycle in a linked list?
struct Node { val: i32, next: Option }
fn has_cycle(head: &Option) -> bool {
let mut slow = head.as_ref();
let mut fast = head.as_ref();
while fast.is_some() && fast.unwrap().next.is_some() {
slow = slow.unwrap().next.as_ref();
fast = fast.unwrap().next.as_ref().unwrap().next.as_ref();
if slow.map(|n| n as *const ()) == fast.map(|n| n as *const ()) {
return true;
}
}
false
}
// List: 1 -> 2 -> 3 -> 4 -> 2 (cycle back to node with value 2)
medium
A. Infinite loop
B. false
C. true
D. Compilation error
Solution
Step 1: Understand the list structure
The list has a cycle starting at node with value 2, so cycle exists.
Step 2: Trace Floyd's pointers
Slow and fast pointers will eventually meet inside the cycle, returning true.
Final Answer:
true -> Option C
Quick Check:
Cycle present = true [OK]
Hint: Cycle in list means pointers meet = true [OK]
Common Mistakes:
Assuming no cycle returns true
Confusing Option with references
Missing unwrap() causing panic
4. Identify the bug in this Rust code snippet for detecting a cycle using Floyd's algorithm:
fn has_cycle(head: &Option) -> bool {
let mut slow = head.as_ref();
let mut fast = head.as_ref();
while fast.is_some() && fast.unwrap().next.is_some() {
slow = slow.unwrap().next.as_ref();
fast = fast.unwrap().next.as_ref(); // Bug here
if slow.map(|n| n as *const ()) == fast.map(|n| n as *const ()) {
return true;
}
}
false
}
medium
A. slow pointer moves two steps instead of one
B. fast pointer moves only one step instead of two
C. Missing check for slow being None
D. Incorrect comparison of slow and fast pointers
Solution
Step 1: Analyze fast pointer movement
Fast pointer should move two steps each loop, but here it moves only one step.
Step 2: Understand impact on cycle detection
Moving fast only one step breaks Floyd's logic, so cycle detection fails or slows.
Final Answer:
fast pointer moves only one step instead of two -> Option B
Quick Check:
Fast pointer must move two steps [OK]
Hint: Fast pointer must jump two nodes each iteration [OK]
Common Mistakes:
Moving fast pointer one step only
Not checking fast pointer's next before moving
Comparing pointers incorrectly
5. Given a linked list where the last node points back to the head (forming a cycle), how can you modify Floyd's algorithm to find the exact node where the cycle begins?
hard
A. Use a hash set to store nodes and find first repeated node
B. Count nodes until slow and fast meet, then return that count as cycle start
C. Reverse the list and check where reversal breaks
D. After detecting cycle, reset slow to head and move both pointers one step until they meet
Solution
Step 1: Detect cycle using Floyd's algorithm
First, detect if cycle exists by moving slow and fast pointers.
Step 2: Find cycle start node
Reset slow to head, then move slow and fast one step each until they meet; meeting point is cycle start.
Final Answer:
After detecting cycle, reset slow to head and move both pointers one step until they meet -> Option D
Quick Check:
Reset slow and move both pointers to find cycle start [OK]
Hint: Reset slow to head after cycle detection to find start [OK]
Common Mistakes:
Trying to count nodes instead of pointer moves
Using extra memory instead of pointer reset
Reversing list which breaks cycle detection
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.