DSALinear Patterns (1D)Tortoise and Hare

Tortoise and Hare

Linear Patterns (1D)

To catch someone on a circular track, you don't run at the same speed. You run faster. Eventually, you're guaranteed to meet.

How can you detect a cycle in a sequence? Try this problem before reading on.

Problem: Linked List Cycle: (LeetCode Link) : Given a linked list, determine if it has a cycle in it. 💡 Hint

One approach to solve the above problem is to store every node you visit in a hash set, but do we really need to use extra space? The most optimal solution here is to use the tortoise and hare algorithm (fast and slow pointers).

0
1
2
3
4
5
6
7
🐢
🐇

How It Works

The general algorithm is as follows:

  1. Initialize Pointers: Start both slow and fast pointers at the beginning of the list.
  2. Iterate with Different Speeds: In a loop, move slow by one step (slow = slow.next) and fast by two steps (fast = fast.next.next).
  3. Safely Handle Edge Cases: Ensure that the fast pointer does not go out of bounds, especially in linked lists.
  4. Identify End State:
    • If the fast pointer meets the slow pointer, a cycle exists.
    • If fast pointer reaches the end of the list, slow pointer is at or near the middle of the list.

Walkthrough: Solving "Linked List Cycle"

def hasCycle(head):
    if not head or not head.next:
        return False

    slow = head
    fast = head

    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next

        if slow == fast:
            return True

    return False

Complexity Analysis

  • Time Complexity: O(n)O(n) - Although the fast pointer moves faster, the total number of steps is proportional to the number of nodes in the list.
  • Space Complexity: O(1)O(1) - Only two pointers are used, regardless of the size of the list.

Variation: Read and Write Pointers

Another variation of this pattern is the Read-Write Pointer. This is often used to modify an array in-place.

  • How it Works: One pointer (read) iterates through the array to examine every element. A second pointer (write) lags behind, only moving when it needs to place a valid element. This ensures that you don't overwrite data before you've had a chance to read it.
  • Practice Problem: Remove Duplicates from Sorted Array (LeetCode Link). 💡 Hint

More Problems & Variations

  1. Middle of the Linked List: Find the middle node of a linked list 💡 Hint
  2. Remove Nth Node From End of List: Remove the nth node from the end of a linked list in one pass 💡 Hint
  3. Move Zeroes: Move all zeroes to the end of the array while maintaining the order of non-zero elements 💡 Hint
  4. Linked List Cycle II: You know how to detect cycles, but can you find out where it begins? 💡 Hint