leetcode_gym/_problems/llcycle2.md
2026-08-25 19:14:07 -06:00

118 lines
2.8 KiB
Markdown

---
layout: page
title: Linked List Cycle II
last_solved: 2020-06-25
category: linked list, cycle detection
leetcode_url: https://leetcode.com/problems/linked-list-cycle-ii
status: Solved
---
Problem
-------
```
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
Note: Do not modify the linked list.
Example 1:
Input: head = [3,2,0,-4], pos = 1
Output: tail connects to node index 1
Explanation: There is a cycle in the linked list, where tail connects to the second node.
Example 2:
Input: head = [1,2], pos = 0
Output: tail connects to node index 0
Explanation: There is a cycle in the linked list, where tail connects to the first node.
Example 3:
Input: head = [1], pos = -1
Output: no cycle
Explanation: There is no cycle in the linked list.
```
Solution
----------
Here's the correct algorithm (similiar to [Find the Duplicate Number](/problems/findTheDuplicateNumber)). However, since we're dealing with linked lists, we have to do error checks.
{% highlight python %}
def detectCycle(self, head: ListNode) -> ListNode:
slow = head
fast = head
# find intersection in cycle
while True:
slow = slow.next
fast = fast.next.next
if slow is fast:
break
# reset slow back to head and find entrance
# the gap between the beginning and entrance == gap between fast and entrance
# (this only applies if fast moved 2x as fast as slow)
slow = head
while slow!=fast:
slow = slow.next
fast = fast.next
return slow
{% endhighlight %}
_____________________
After adding null checks and followed the tips from [Linked List Cycle I](/problems/llcycle)
This one we need to start both slow and fast at head. `fast` cannot be `head.next` because where fast ends needs to be equidistance to the entrance.
{% highlight python %}
def detectCycle(self, head: ListNode) -> ListNode:
if not head: return None
slow = head
fast = head
# find intersection in cycle
while True:
if slow is None or fast is None or fast.next is None:
return None
slow = slow.next
fast = fast.next.next
if slow is fast:
break
# reset slow back to head and find entrance
# the gap between the beginning and entrance == gap between fast and entrance
# (this only applies if fast moved 2x as fast as slow)
slow = head
while slow!=fast:
slow = slow.next
fast = fast.next
return slow
{% endhighlight %}
![image1]()