Once you detect a cycle, finding where it starts requires a clever insight.
After fast and slow meet inside the cycle, reset one pointer to the head. Move both pointers one step at a time. They'll meet at the cycle start.
# After detecting cycle (slow == fast)
slow = head
while slow != fast:
slow = slow.next
fast = fast.next
return slow # cycle start
Why does this work? Let = distance from head to cycle start, = distance from cycle start to meeting point, = cycle length.
When they first meet: slow traveled , fast traveled for some . Since fast moves twice as fast: , so . So walking steps from the meeting point lands exactly at the cycle start.