|
8 | 8 |
|
9 | 9 |
|
10 | 10 | def has_cycle(head: ListNode) -> Optional[ListNode]: |
11 | | - # TODO - you fill in here. |
| 11 | + """Return None if there is no cycle, or the node at the start |
| 12 | + of the cycle if there is a cycle.""" |
| 13 | + |
| 14 | + # If list has only 1 element, no cycle. |
| 15 | + if not head: |
| 16 | + return None |
| 17 | + if not head.next: |
| 18 | + return None |
| 19 | + |
| 20 | + # Slow and fast node. |
| 21 | + slow, fast = head, head |
| 22 | + i = 0 |
| 23 | + while fast.next and fast.next.next: |
| 24 | + # Move fast up every round. |
| 25 | + fast = fast.next |
| 26 | + # Move slow up every other round. |
| 27 | + if i % 2: |
| 28 | + slow = slow.next |
| 29 | + |
| 30 | + # Detect cycle |
| 31 | + if fast is slow or fast.next is slow: |
| 32 | + # We have a cycle! |
| 33 | + # We can count the length of the cycle in O(n) time by |
| 34 | + # freezing slow and moving fast until it hits slow again. |
| 35 | + fast = slow.next |
| 36 | + cycle_length = 1 |
| 37 | + while fast is not slow: |
| 38 | + fast = fast.next |
| 39 | + cycle_length += 1 |
| 40 | + print(cycle_length) |
| 41 | + |
| 42 | + # Now that we have cycle length, we just start fast and slow at head. |
| 43 | + # increment slow after incrementing fast cycle_length times. once |
| 44 | + # fast is slow, slow is the start of the cycle. |
| 45 | + fast, slow = head, head |
| 46 | + for _ in range(cycle_length): |
| 47 | + fast = fast.next |
| 48 | + |
| 49 | + while fast is not slow: |
| 50 | + fast = fast.next |
| 51 | + slow = slow.next |
| 52 | + |
| 53 | + return slow |
| 54 | + |
| 55 | + i += 1 |
| 56 | + |
| 57 | + # If we reach the end (fast.next is None). |
12 | 58 | return None |
13 | 59 |
|
14 | 60 |
|
@@ -42,6 +88,10 @@ def has_cycle_wrapper(executor, head, cycle_idx): |
42 | 88 | if result is None: |
43 | 89 | raise TestFailure('Existing cycle was not found') |
44 | 90 | cursor = result |
| 91 | + if result.data != cycle_idx: |
| 92 | + raise TestFailure( |
| 93 | + f"Returned node {result.data} is not the start of the cycle {cycle_idx}" |
| 94 | + ) |
45 | 95 | while True: |
46 | 96 | cursor = cursor.next |
47 | 97 | cycle_length -= 1 |
|
0 commit comments