Hone logo
Hone
Problems

Detect Cycles in a Linked List Using Floyd's Tortoise and Hare Algorithm in Rust

This challenge focuses on implementing a classic algorithm for detecting cycles within a singly linked list. Cycle detection is a fundamental problem in computer science, with applications ranging from detecting infinite loops in program execution to identifying issues in data structures. You will implement Floyd's Tortoise and Hare algorithm in Rust to efficiently determine if a given linked list contains a cycle.

Problem Description

Your task is to write a Rust function that takes the head of a singly linked list as input and returns a boolean value indicating whether the list contains a cycle.

A singly linked list is a data structure where each node contains a value and a pointer to the next node in the sequence. A cycle exists if, by following the next pointers, you eventually return to a node that has already been visited.

Key Requirements:

  • Implement the function has_cycle that accepts an Option<Box<ListNode>> representing the head of the linked list.
  • The function should return true if a cycle is detected, and false otherwise.
  • You must use Floyd's Tortoise and Hare algorithm. This algorithm uses two pointers, one moving at a single speed (the tortoise) and another moving at double speed (the hare). If there's a cycle, the hare will eventually "lap" the tortoise.
  • The solution should be memory-efficient, ideally O(1) space complexity.

Expected Behavior:

  • If the list is empty or has only one node without a cycle, the function should return false.
  • If the list has a cycle, the function should return true.

Edge Cases to Consider:

  • An empty list.
  • A list with a single node.
  • A list with no cycle.
  • A list where the cycle starts at the head.
  • A list where the cycle is at the very end of the list.

Examples

Example 1:

Input: A linked list representing [3, 2, 0, -4] where the node with value -4 points back to the node with value 2.
ListNode {
    val: 3,
    next: Some(Box::new(ListNode {
        val: 2,
        next: Some(Box::new(ListNode {
            val: 0,
            next: Some(Box::new(ListNode {
                val: -4,
                next: Some(Box::new(ListNode { // Cycle: -4 points back to node with value 2
                    val: 2,
                    next: None, // This next field is conceptually ignored due to the cycle
                }))
            }))
        }))
    }))
}
// The above representation is a simplified conceptual view for understanding.
// In a real implementation, you would need to manage pointers to create the cycle.
// For this challenge, assume the ListNode struct is provided and you can construct such lists.

Output: true
Explanation: The hare (moving twice as fast) will eventually catch up to the tortoise within the cycle.

Example 2:

Input: A linked list representing [1, 2] where the node with value 2 points back to the node with value 1.

Output: true
Explanation: Similar to Example 1, the hare will catch the tortoise.

Example 3:

Input: A linked list representing [1] with no cycle.

Output: false
Explanation: The list is too short for a cycle to form, and the hare will reach the end of the list.

Example 4:

Input: A linked list representing [1, 2, 3, 4] with no cycle.

Output: false
Explanation: The hare will reach the end of the list without ever meeting the tortoise.

Constraints

  • The number of nodes in the linked list can be between 0 and 10<sup>5</sup>.
  • The value of each node can be any integer.
  • Your solution should aim for O(n) time complexity, where n is the number of nodes in the list.
  • Your solution should achieve O(1) space complexity (excluding the space taken by the input linked list itself).

Notes

  • You will need to define the ListNode struct. It should contain a val (integer) and a next field (an Option<Box<ListNode>>).
  • Be careful with handling None pointers to avoid panics.
  • Consider the initial state of your tortoise and hare pointers.
  • The core idea is that if a cycle exists, the hare will eventually catch up to the tortoise. If the hare reaches the end of the list (None), then there is no cycle.
  • This challenge is a good opportunity to practice Rust's ownership and borrowing rules when dealing with potentially recursive data structures like linked lists.
Loading editor...
rust