Skip to content

Commit 0139ac5

Browse files
committed
feat: add solutions to lc problem: No.0142
No.0142.Linked List Cycle II
1 parent 05f5809 commit 0139ac5

File tree

8 files changed

+338
-345
lines changed

8 files changed

+338
-345
lines changed

solution/0100-0199/0142.Linked List Cycle II/README.md

Lines changed: 113 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -65,19 +65,25 @@
6565

6666
<!-- 这里可写通用的实现逻辑 -->
6767

68-
先利用快慢指针判断链表是否有环,没有环则直接返回 `null`
68+
**方法一:快慢指针**
6969

70-
若链表有环,我们分析快慢相遇时走过的距离
70+
我们先利用快慢指针判断链表是否有环,如果有环的话,快慢指针一定会相遇,且相遇的节点一定在环中
7171

72-
对于慢指针(每次走 1 步),走过的距离为 `S=X+Y` ①;快指针(每次走 2 步)走过的距离为 `2S=X+Y+N(Y+Z)` ②。如下图所示,其中 `N` 表示快指针与慢指针相遇时在环中所走过的圈数,而我们要求的环入口,也即是 `X` 的距离:
72+
如果没有环,快指针会先到达链表尾部,直接返回 `null` 即可。
7373

74-
![](./images/linked-list-cycle-ii.png)
74+
如果有环,我们再定义一个答案指针 $ans$ 指向链表头部,然后让 $ans$ 和慢指针一起向前走,每次走一步,直到 $ans$ 和慢指针相遇,相遇的节点即为环的入口节点。
7575

76-
我们根据式子 ①②,得出 `X+Y=N(Y+Z)` => `X=(N-1)(Y+Z)+Z`
76+
为什么这样能找到环的入口节点呢?
7777

78-
`N=1`(快指针在环中走了一圈与慢指针相遇) 时,`X=(1-1)(Y+Z)+Z`,即 `X=Z`。此时只要定义一个 `p` 指针指向头节点,然后慢指针与 `p` 开始同时走,当慢指针与 `p` 相遇时,也就到达了环入口,直接返回 `p` 即可
78+
我们不妨假设链表头节点到环入口的距离为 $x$,环入口到相遇节点的距离为 $y$,相遇节点到环入口的距离为 $z$,那么慢指针走过的距离为 $x + y$,快指针走过的距离为 $x + y + k \times (y + z)$,其中 $k$ 是快指针在环中绕了 $k$ 圈
7979

80-
`N>1`时,也是同样的,说明慢指针除了走 `Z` 步,还需要绕 `N-1` 圈才能与 `p` 相遇。
80+
<p><img src="https://fastly.jsdelivr.net/gh/doocs/leetcode@main/solution/0100-0199/0142.Linked%20List%20Cycle%20II/images/linked-list-cycle-ii.png" /></p>
81+
82+
由于快指针速度是慢指针的 $2$ 倍,因此有 $2 \times (x + y) = x + y + k \times (y + z)$,可以推出 $x + y = k \times (y + z)$,即 $x = (k - 1) \times (y + z) + z$。
83+
84+
也即是说,如果我们定义一个答案指针 $ans$ 指向链表头部,然后 $ans$ 和慢指针一起向前走,那么它们一定会在环入口相遇。
85+
86+
时间复杂度 $O(n)$,其中 $n$ 是链表中节点的数目。空间复杂度 $O(1)$。
8187

8288
<!-- tabs:start -->
8389

@@ -94,18 +100,17 @@
94100

95101

96102
class Solution:
97-
def detectCycle(self, head: ListNode) -> ListNode:
98-
slow = fast = head
99-
has_cycle = False
100-
while not has_cycle and fast and fast.next:
101-
slow, fast = slow.next, fast.next.next
102-
has_cycle = slow == fast
103-
if not has_cycle:
104-
return None
105-
p = head
106-
while p != slow:
107-
p, slow = p.next, slow.next
108-
return p
103+
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
104+
fast = slow = head
105+
while fast and fast.next:
106+
slow = slow.next
107+
fast = fast.next.next
108+
if slow == fast:
109+
ans = head
110+
while ans != slow:
111+
ans = ans.next
112+
slow = slow.next
113+
return ans
109114
```
110115

111116
### **Java**
@@ -126,23 +131,82 @@ class Solution:
126131
*/
127132
public class Solution {
128133
public ListNode detectCycle(ListNode head) {
129-
ListNode slow = head, fast = head;
130-
boolean hasCycle = false;
131-
while (!hasCycle && fast != null && fast.next != null) {
134+
ListNode fast = head, slow = head;
135+
while (fast != null && fast.next != null) {
132136
slow = slow.next;
133137
fast = fast.next.next;
134-
hasCycle = slow == fast;
135-
}
136-
if (!hasCycle) {
137-
return null;
138+
if (slow == fast) {
139+
ListNode ans = head;
140+
while (ans != slow) {
141+
ans = ans.next;
142+
slow = slow.next;
143+
}
144+
return ans;
145+
}
138146
}
139-
ListNode p = head;
140-
while (p != slow) {
141-
p = p.next;
142-
slow = slow.next;
147+
return null;
148+
}
149+
}
150+
```
151+
152+
### **C++**
153+
154+
```cpp
155+
/**
156+
* Definition for singly-linked list.
157+
* struct ListNode {
158+
* int val;
159+
* ListNode *next;
160+
* ListNode(int x) : val(x), next(NULL) {}
161+
* };
162+
*/
163+
class Solution {
164+
public:
165+
ListNode *detectCycle(ListNode *head) {
166+
ListNode* fast = head;
167+
ListNode* slow = head;
168+
while (fast && fast->next) {
169+
slow = slow->next;
170+
fast = fast->next->next;
171+
if (slow == fast) {
172+
ListNode* ans = head;
173+
while (ans != slow) {
174+
ans = ans->next;
175+
slow = slow->next;
176+
}
177+
return ans;
178+
}
143179
}
144-
return p;
180+
return nullptr;
145181
}
182+
};
183+
```
184+
185+
### **Go**
186+
187+
```go
188+
/**
189+
* Definition for singly-linked list.
190+
* type ListNode struct {
191+
* Val int
192+
* Next *ListNode
193+
* }
194+
*/
195+
func detectCycle(head *ListNode) *ListNode {
196+
fast, slow := head, head
197+
for fast != nil && fast.Next != nil {
198+
slow = slow.Next
199+
fast = fast.Next.Next
200+
if slow == fast {
201+
ans := head
202+
for ans != slow {
203+
ans = ans.Next
204+
slow = slow.Next
205+
}
206+
return ans
207+
}
208+
}
209+
return nil
146210
}
147211
```
148212

@@ -162,61 +226,23 @@ public class Solution {
162226
*/
163227

164228
function detectCycle(head: ListNode | null): ListNode | null {
165-
let slow = head,
166-
fast = head;
167-
while (fast) {
229+
let [slow, fast] = [head, head];
230+
while (fast && fast.next) {
168231
slow = slow.next;
169-
if (!fast.next) return null;
170232
fast = fast.next.next;
171-
172-
if (fast == slow) {
173-
let cur = head;
174-
while (cur != slow) {
233+
if (slow === fast) {
234+
let ans = head;
235+
while (ans !== slow) {
236+
ans = ans.next;
175237
slow = slow.next;
176-
cur = cur.next;
177238
}
178-
return cur;
239+
return ans;
179240
}
180241
}
181242
return null;
182243
}
183244
```
184245

185-
### **C++**
186-
187-
```cpp
188-
/**
189-
* Definition for singly-linked list.
190-
* struct ListNode {
191-
* int val;
192-
* ListNode *next;
193-
* ListNode(int x) : val(x), next(NULL) {}
194-
* };
195-
*/
196-
class Solution {
197-
public:
198-
ListNode* detectCycle(ListNode* head) {
199-
ListNode* slow = head;
200-
ListNode* fast = head;
201-
bool hasCycle = false;
202-
while (!hasCycle && fast && fast->next) {
203-
slow = slow->next;
204-
fast = fast->next->next;
205-
hasCycle = slow == fast;
206-
}
207-
if (!hasCycle) {
208-
return nullptr;
209-
}
210-
ListNode* p = head;
211-
while (p != slow) {
212-
p = p->next;
213-
slow = slow->next;
214-
}
215-
return p;
216-
}
217-
};
218-
```
219-
220246
### **JavaScript**
221247

222248
```js
@@ -233,54 +259,23 @@ public:
233259
* @return {ListNode}
234260
*/
235261
var detectCycle = function (head) {
236-
let slow = head;
237-
let fast = head;
238-
let hasCycle = false;
239-
while (!hasCycle && fast && fast.next) {
262+
let [slow, fast] = [head, head];
263+
while (fast && fast.next) {
240264
slow = slow.next;
241265
fast = fast.next.next;
242-
hasCycle = slow == fast;
243-
}
244-
if (!hasCycle) {
245-
return null;
246-
}
247-
let p = head;
248-
while (p != slow) {
249-
p = p.next;
250-
slow = slow.next;
266+
if (slow === fast) {
267+
let ans = head;
268+
while (ans !== slow) {
269+
ans = ans.next;
270+
slow = slow.next;
271+
}
272+
return ans;
273+
}
251274
}
252-
return p;
275+
return null;
253276
};
254277
```
255278

256-
### **Go**
257-
258-
```go
259-
/**
260-
* Definition for singly-linked list.
261-
* type ListNode struct {
262-
* Val int
263-
* Next *ListNode
264-
* }
265-
*/
266-
func detectCycle(head *ListNode) *ListNode {
267-
slow, fast := head, head
268-
hasCycle := false
269-
for !hasCycle && fast != nil && fast.Next != nil {
270-
slow, fast = slow.Next, fast.Next.Next
271-
hasCycle = slow == fast
272-
}
273-
if !hasCycle {
274-
return nil
275-
}
276-
p := head
277-
for p != slow {
278-
p, slow = p.Next, slow.Next
279-
}
280-
return p
281-
}
282-
```
283-
284279
### **...**
285280

286281
```

0 commit comments

Comments
 (0)