Hello! In our last lesson, we focused on reversing a linked list, which gave you excellent practice with pointer manipulation. That skill will be essential today as we tackle another classic interview problem.
This lesson addresses a common scenario: what if a linked list isn't linear? What if it contains a cycle, where a node's next pointer points back to a previous node in the list? Your learning outcome for today is to detect and find the starting node of a cycle in a linked list using Floyd's algorithm.
This problem is a favorite in technical interviews because its optimal solution is not immediately obvious and relies on a clever pointer manipulation technique known as Floyd's Tortoise and Hare algorithm. Mastering this will not only add a powerful tool to your problem-solving arsenal but also deepen your understanding of how pointers can be used in non-trivial ways.

1. A Straightforward but Inefficient Approach: Hashing
Before we dive into the optimal solution, let's consider a more intuitive approach. How can we detect a revisited node? By keeping a record of every node we've already seen.
The idea is simple:
- Create a
HashSetto storeListNodeobjects. - Traverse the linked list from the head.
- For each node, check if it's already in the
HashSet.- If it is, we've found a cycle! The current node is the starting point of the loop.
- If it's not, add the current node to the
HashSetand move to the next node.
- If we reach the end of the list (
null), it means no node was revisited, so there is no cycle.
This approach is correct, but what are its performance characteristics?
- Time Complexity: , where N is the number of nodes in the list, because we visit each node at most once.
- Space Complexity: , because in the worst case (a list with a cycle involving all nodes, or a linear list), we would store every node in the
HashSet.
For an interview setting, an O(N) space complexity is often a signal to look for a more optimized, constant-space solution. Let's watch a short video segment that explains this hashing method.
L17. Find the starting point of the Loop/Cycle in LinkedList | Multiple Approaches
The video 'L17. Find the starting point of the Loop/Cycle in LinkedList' from the 'take U forward' channel begins by explaining this hashing-based brute-force approach. It clearly sets up the problem and the motivation for a more optimal solution.
Watch the first part of the video, from 00:03 to 07:04. Focus on understanding the logic of using a hash set and the analysis of its time and space complexity.
2. The Optimal Solution: Floyd's Tortoise and Hare Algorithm
To achieve a constant space complexity, we can use a clever two-pointer technique. We'll use:
- A slow pointer that moves one step at a time (
slow = slow.next). - A fast pointer that moves two steps at a time (
fast = fast.next.next).
The algorithm works in two distinct phases.
Phase 1: Cycle Detection
Both pointers start at the head. They then traverse the list at their respective speeds.
- If the list is linear (no cycle), the
fastpointer will eventually reach the end (null), and we can conclude there's no cycle. - If the list contains a cycle, the
fastpointer will enter the loop and start circling. Theslowpointer will eventually follow it into the loop. Since thefastpointer is moving faster, it will inevitably "lap" theslowpointer and they will collide at some node within the cycle.
The moment slow == fast, we have successfully detected a cycle.

This video segment recaps the detection phase.
L17. Find the starting point of the Loop/Cycle in LinkedList | Multiple Approaches
Let's continue with the 'take U forward' video to see the first phase of Floyd's algorithm in action.
Watch from 07:04 to 09:52. This part demonstrates how the slow and fast pointers are used to confirm the existence of a loop.
Phase 2: Finding the Start of the Cycle
Detecting the cycle is only half the battle. The core of the problem is finding the exact node where the cycle begins. Here's the magic trick:
- Once
slowandfastmeet, leave thefastpointer at the collision point. - Reset the
slowpointer back to theheadof the list. - Now, move both pointers one step at a time (
slow = slow.nextandfast = fast.next). - The node where they meet again is the starting node of the cycle.
Let's see this second phase explained visually.
L17. Find the starting point of the Loop/Cycle in LinkedList | Multiple Approaches
The next part of the video details the algorithm for finding the starting node after a collision has occurred.
Watch from 09:52 to 11:34. Pay close attention to the procedure: resetting one pointer to the head and then moving both pointers at the same speed.
Why Does This Work? The Mathematical Intuition
You might be wondering why this procedure correctly identifies the start of the loop. It's based on the distances the pointers travel. Let's define:
L1: The distance from theheadto the start of the loop.L2: The distance from the start of the loop to the collision point.C: The length of the cycle.
When the slow and fast pointers collide:
- Distance traveled by slow pointer:
D(slow) = L1 + L2 - Distance traveled by fast pointer:
D(fast) = L1 + L2 + k * C(it has completedkextra laps of the cycle)
Since the fast pointer moves twice as fast, D(fast) = 2 * D(slow).
Substituting the distances:L1 + L2 + k * C = 2 * (L1 + L2)L1 + L2 + k * C = 2*L1 + 2*L2k * C = L1 + L2
Rearranging this gives: L1 = k * C - L2
This equation is the key. It tells us that the distance from the head to the loop start (L1) is equal to some number of full cycles minus the distance from the loop start to the collision point (L2). This effectively means that the distance from the head to the loop start is the same as the distance from the collision point to the loop start, if you traverse forward inside the loop.
Therefore, by placing one pointer at the head and another at the collision point and moving them at the same speed, they are guaranteed to meet at the start of the loop.
The following video provides an excellent, detailed walkthrough of this proof. Understanding this is what separates a good candidate from a great one in an interview.
L17. Find the starting point of the Loop/Cycle in LinkedList | Multiple Approaches
This final segment from the 'take U forward' video provides a clear mathematical and intuitive proof for why Floyd's algorithm works. This is the most crucial part for a deep understanding.
Watch from 14:22 to 21:55. Don't worry if you need to re-watch it. The goal is to grasp the relationship between the distances covered by the pointers.
3. Java Implementation
Now, let's translate this two-phase algorithm into Java code. The structure directly follows the logic we've discussed.
Detect Linked List Cycle Start Node (Floyd's Algorithm)
The article 'Detect Linked List Cycle Start Node (Floyd's Algorithm)' provides a very clean and well-commented Java implementation of this algorithm. It's a great reference for seeing the logic in code.
Please read the section 'Code (Java)' and compare it to the steps we've outlined. Notice how the code is structured into two clear phases within the same function.
Here's the implementation from the article, which perfectly captures the algorithm:
// Assuming a ListNode class is defined:
// class ListNode {
// int val;
// ListNode next;
// ListNode(int x) { val = x; next = null; }
// }
public class Solution {
public ListNode detectCycle(ListNode head) {
if (head == null || head.next == null) {
return null; // No cycle can exist
}
ListNode slow = head;
ListNode fast = head;
// Phase 1: Detect if a cycle exists
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
// Cycle detected, start Phase 2
// Reset one pointer to the head
slow = head;
// Move both pointers one step at a time until they meet
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
// The meeting point is the start of the cycle
return slow;
}
}
// If the loop finishes, fast reached null, so no cycle
return null;
}
}
- Time Complexity: . Although we have two loops, the pointers traverse the list a constant number of times in total, making it linear.
- Space Complexity: . This is the key advantage. We only use two pointers, regardless of the list's size.
Test your understanding!
Imagine a linked list where the non-cyclic part has length L1 = 5 nodes, and the cycle itself has length C = 8 nodes.
- When the slow and fast pointers first collide, how many steps has the slow pointer taken?
- At which node inside the cycle (relative to the cycle start) do they collide?
Show answer
Let the collision point be L2 nodes past the cycle start. From our proof, we know L1 = k*C - L2.
-
We have
5 = k * 8 - L2. To find the smallest positivekandL2(where0 <= L2 < 8), we can testk=1. Ifk=1, then5 = 8 - L2, which givesL2 = 3. This is a valid distance within the cycle. -
The slow pointer travels a distance of
L1 + L2. So, it takes5 + 3 = 8steps to reach the collision point. -
They collide at the node that is 3 steps past the start of the cycle.
Let's check this:
- Slow pointer: 8 steps.
- Fast pointer: 16 steps.
The fast pointer travelsL1(5 steps) to enter the cycle. It has16 - 5 = 11steps left. It completes one full cycle of 8 steps and then moves 3 more steps, landing at the same spot as the slow pointer (L2=3). The math holds!
Conclusion
Excellent work! You've just learned one of the most elegant algorithms for linked lists. It's a testament to how clever pointer manipulation can solve complex problems with remarkable efficiency.
Key Takeaways:
- Hashing vs. Floyd's: While hashing is an intuitive
O(N)space solution, Floyd's Tortoise and Hare algorithm provides an optimalO(1)space solution. - Two-Phase Process: Floyd's algorithm consists of two phases: first, detect a collision using slow and fast pointers, and second, find the cycle's start by resetting one pointer to the head and moving both at the same speed.
- The "Why": The algorithm works because of the mathematical relationship between the distance from the head to the loop start and the distance from the collision point to the loop start.
Preview of the next lesson:
The slow-and-fast pointer technique is incredibly versatile. In our next lesson, we will use it again to solve another common problem: finding the middle element of a linked list. This will help reinforce the pattern and show you how it can be adapted to different scenarios.