Find Out if a Linked List has a Cycle

Without marking nodes, find out if a linked list has a cycle in it or not.

2026 Update: Floyd’s Cycle Detection — Tortoise and Hare

Detecting a cycle in a linked list is solved by Floyd’s algorithm (tortoise and hare): two pointers at different speeds. If there’s a cycle, the fast pointer eventually laps the slow pointer. If not, the fast pointer reaches null.

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

# Level 1: Detect if cycle exists — O(n) time, O(1) space
def has_cycle(head: ListNode) -> bool:
    """Floyd's cycle detection: slow moves 1 step, fast moves 2 steps."""
    slow = fast = head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            return True
    return False

# Level 2: Find the START of the cycle — key insight
def detect_cycle_start(head: ListNode) -> ListNode:
    """
    After slow and fast meet:
    Reset one pointer to head, keep other at meeting point.
    Both advance one step at a time → they meet at cycle start.

    PROOF: If head→cycle_start = F steps, cycle_start→meeting = a steps,
    cycle length = C. Then: slow traveled F+a, fast traveled F+a+C (one full loop).
    Since fast = 2×slow: F+a+C = 2(F+a) → C = F+a → F = C-a.
    So moving F steps from head = moving C-a steps around cycle from meeting point
    = arriving at cycle start.
    """
    slow = fast = head
    # Phase 1: find meeting point
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            break
    else:
        return None  # No cycle

    # Phase 2: find cycle start
    slow = head
    while slow != fast:
        slow = slow.next
        fast = fast.next
    return slow

# Level 3: Find cycle length
def cycle_length(head: ListNode) -> int:
    slow = fast = head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            # Count steps around cycle
            count = 1
            fast = fast.next
            while fast != slow:
                fast = fast.next
                count += 1
            return count
    return 0

# Build a list with a cycle for testing
def build_cyclic_list(values, cycle_pos):
    """cycle_pos: index of node where tail connects back to (-1 for no cycle)."""
    nodes = [ListNode(v) for v in values]
    for i in range(len(nodes) - 1):
        nodes[i].next = nodes[i+1]
    if cycle_pos >= 0:
        nodes[-1].next = nodes[cycle_pos]
    return nodes[0] if nodes else None

# Test
head = build_cyclic_list([3, 2, 0, -4], cycle_pos=1)  # Tail → node at index 1
print(has_cycle(head))           # True
start = detect_cycle_start(head)
print(start.val)                 # 2 (value at cycle start)
print(cycle_length(head))        # 3 (2→0→-4→2)

Applications of cycle detection beyond linked lists:

  • Functional graph cycles: Finding cycles in functions f: S→S (e.g., hash collisions)
  • Rho algorithm: Pollard’s integer factorization uses Floyd’s cycle detection
  • Happy number: LeetCode #202 — cycle detection in digit-square sequences
  • Find duplicate in array: LeetCode #287 — treat array as linked list with cycles

LeetCode #141 (Linked List Cycle), #142 (Linked List Cycle II). The cycle-start proof via the F = C-a relationship is a common “explain the math” follow-up.

💡Strategies for Solving This Problem

Classic Problem, Elegant Solution

Got this at Amazon. It's a standard problem but the solution (Floyd's Cycle Detection) is so clever that when you see it, it clicks forever.

The Insight

Imagine two runners on a circular track. If one runs twice as fast, they'll eventually lap the slower runner. Same idea with pointers in a linked list.

Floyd's Algorithm (Tortoise and Hare)

  • Use two pointers: slow (moves 1 step) and fast (moves 2 steps)
  • If there's a cycle, fast will eventually catch up to slow
  • If there's no cycle, fast reaches the end (null)

This is O(n) time and O(1) space. You can't do better.

Alternative: Hash Set (Not Optimal)

Store visited nodes in a Set. If you see a node twice, there's a cycle. Works but uses O(n) space. My Amazon interviewer said "Can you do it without extra space?" - that's your cue for Floyd's.

Follow-Up Questions They'll Ask

  1. "Where does the cycle begin?" - This is the hard part. After detecting a cycle, there's a mathematical proof about where the entry point is.
  2. "What's the length of the cycle?" - Once pointers meet, count how many steps until they meet again.

I didn't know these follow-ups in my first Amazon interview. Study them.

Scroll to Top