Cycle Detection in a Linked List
Cycle detection is a fundamental problem in data structures, particularly relevant when working with linked lists. This challenge asks you to implement a function that determines whether a singly linked list contains a cycle (a loop where the last node points back to a previous node). Detecting cycles is crucial for preventing infinite loops and ensuring the integrity of algorithms that traverse linked lists.
Problem Description
You are given a singly linked list represented as a vector of Option<usize>. Each element in the vector represents a node. The value of each node is its index in the vector. If nodes[i] is Some(j), it means the node at index i points to the node at index j. If nodes[i] is None, it means the node at index i is the tail of the list and points to nothing.
Your task is to write a function has_cycle(nodes: &Vec<Option<usize>>) that returns true if the linked list contains a cycle and false otherwise. You should implement the cycle detection using Floyd's Tortoise and Hare algorithm (also known as the slow and fast pointer approach).
Key Requirements:
- The function must take a reference to a vector of
Option<usize>representing the linked list. - The function must return a boolean value indicating whether a cycle exists.
- The function must use Floyd's Tortoise and Hare algorithm.
- The function should handle empty lists gracefully.
- The function should handle lists with only one node gracefully.
Expected Behavior:
The function should traverse the linked list using two pointers: a slow pointer that moves one step at a time and a fast pointer that moves two steps at a time. If a cycle exists, the fast pointer will eventually catch up to the slow pointer. If no cycle exists, the fast pointer will reach the end of the list (represented by None).
Edge Cases to Consider:
- Empty list:
[] - List with one node:
[Some(0)]or[None] - Cycle at the beginning of the list
- Cycle in the middle of the list
- List with no cycle
Examples
Example 1:
Input: [Some(1), Some(2), Some(0), None]
Output: true
Explanation: Node 0 points to 1, Node 1 points to 2, Node 2 points to 0, creating a cycle.
Example 2:
Input: [Some(1), Some(2), None, None]
Output: false
Explanation: Node 0 points to 1, Node 1 points to 2, Node 2 points to None, Node 3 points to None. No cycle exists.
Example 3:
Input: [None]
Output: false
Explanation: A single node pointing to nothing does not constitute a cycle.
Example 4:
Input: [Some(0)]
Output: true
Explanation: A single node pointing to itself creates a cycle.
Constraints
- The input vector
nodescan contain at most 1000 elements. - The indices in the
Option<usize>values will always be valid indices within thenodesvector. - The algorithm should have a time complexity of O(n), where n is the number of nodes in the linked list.
- The algorithm should have a space complexity of O(1).
Notes
- Floyd's Tortoise and Hare algorithm is an efficient way to detect cycles in linked lists.
- Consider how to handle the case where the fast pointer reaches the end of the list (i.e.,
None). - Be careful with index out-of-bounds errors when traversing the list. Always check if the next node exists before attempting to access it.
- The
Option<usize>type is used to represent the next node in the linked list.Some(index)means the node points to the node at the given index, andNonemeans the node is the tail.