Skip to content

Fix is_list_cyclic#253

Open
gmstanle wants to merge 2 commits intoadnanaziz:masterfrom
gmstanle:gstanley/fix_is_list_cyclic
Open

Fix is_list_cyclic#253
gmstanle wants to merge 2 commits intoadnanaziz:masterfrom
gmstanle:gstanley/fix_is_list_cyclic

Conversation

@gmstanle
Copy link
Copy Markdown

@gmstanle gmstanle commented Feb 11, 2026

This PR fixes the testing of is_list_cyclic so that it tests for correctly identifying the start of the cycle. This can be verified with the following solution code (SPOILER alert for those who have not solved it):

This solution will succeed on the old code but fail on the PR

def has_cycle(head: ListNode) -> Optional[ListNode]:
    """Return None if there is no cycle, or the node at the start
    of the cycle if there is a cycle."""
    
    # If list has only 1 element, no cycle.
    if not head:
        return None
    if not head.next:
        return None
    
    # Slow and fast node.
    slow, fast = head, head
    i = 0
    while fast.next and fast.next.next:
        # Move fast up every round.
        fast = fast.next
        # Move slow up every other round.
        if i % 2:
            slow = slow.next
        
        # Detect cycle and return slow - this is incorrect but passes current tests
        if fast is slow or fast.next is slow:
            return slow
        
        i += 1
    
    # If we reach the end (fast.next is None).
    return None
    ```
    
    This code was NOT LLM-generated.
    

@gmstanle
Copy link
Copy Markdown
Author

gmstanle commented Feb 11, 2026

This correct code will pass the updated tests:

```
def has_cycle(head: ListNode) -> Optional[ListNode]:
"""Return None if there is no cycle, or the node at the start
of the cycle if there is a cycle."""

# If list has only 1 element, no cycle.
if not head:
    return None
if not head.next:
    return None

# Slow and fast node.
slow, fast = head, head
i = 0
while fast.next and fast.next.next:
    # Move fast up every round.
    fast = fast.next
    # Move slow up every other round.
    if i % 2:
        slow = slow.next
    
    # Detect cycle
    if fast is slow or fast.next is slow:
        # We have a cycle!
        # We can count the length of the cycle in O(n) time by
        # freezing slow and moving fast until it hits slow again.
        fast = slow.next
        cycle_length = 1
        while fast is not slow:
            fast = fast.next
            cycle_length += 1
        print(cycle_length)
        
        # Now that we have cycle length, we just start fast and slow at head.
        # increment slow after incrementing fast cycle_length times. once 
        # fast is slow, slow is the start of the cycle.
        fast, slow = head, head
        for _ in range(cycle_length):
            fast = fast.next
            
        while fast is not slow:
            fast = fast.next
            slow = slow.next
        
        return slow
    
    i += 1

# If we reach the end (fast.next is None).
return None
```

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant