65
65
66
66
<!-- 这里可写通用的实现逻辑 -->
67
67
68
- 先利用快慢指针判断链表是否有环,没有环则直接返回 ` null ` 。
68
+ ** 方法一:快慢指针 **
69
69
70
- 若链表有环,我们分析快慢相遇时走过的距离 。
70
+ 我们先利用快慢指针判断链表是否有环,如果有环的话,快慢指针一定会相遇,且相遇的节点一定在环中 。
71
71
72
- 对于慢指针(每次走 1 步),走过的距离为 ` S=X+Y ` ①;快指针(每次走 2 步)走过的距离为 ` 2S=X+Y+N(Y+Z) ` ②。如下图所示,其中 ` N ` 表示快指针与慢指针相遇时在环中所走过的圈数,而我们要求的环入口,也即是 ` X ` 的距离:
72
+ 如果没有环,快指针会先到达链表尾部,直接返回 ` null ` 即可。
73
73
74
- ![ ] ( ./images/linked-list-cycle-ii.png )
74
+ 如果有环,我们再定义一个答案指针 $ans$ 指向链表头部,然后让 $ans$ 和慢指针一起向前走,每次走一步,直到 $ans$ 和慢指针相遇,相遇的节点即为环的入口节点。
75
75
76
- 我们根据式子 ①②,得出 ` X+Y=N(Y+Z) ` => ` X=(N-1)(Y+Z)+Z ` 。
76
+ 为什么这样能找到环的入口节点呢?
77
77
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$ 圈 。
79
79
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)$。
81
87
82
88
<!-- tabs:start -->
83
89
94
100
95
101
96
102
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
109
114
```
110
115
111
116
### ** Java**
@@ -126,23 +131,82 @@ class Solution:
126
131
*/
127
132
public class Solution {
128
133
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 ) {
132
136
slow = slow. next;
133
137
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
+ }
138
146
}
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
+ }
143
179
}
144
- return p ;
180
+ return nullptr ;
145
181
}
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
146
210
}
147
211
```
148
212
@@ -162,61 +226,23 @@ public class Solution {
162
226
*/
163
227
164
228
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 ) {
168
231
slow = slow .next ;
169
- if (! fast .next ) return null ;
170
232
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 ;
175
237
slow = slow .next ;
176
- cur = cur .next ;
177
238
}
178
- return cur ;
239
+ return ans ;
179
240
}
180
241
}
181
242
return null ;
182
243
}
183
244
```
184
245
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
-
220
246
### ** JavaScript**
221
247
222
248
``` js
@@ -233,54 +259,23 @@ public:
233
259
* @return {ListNode}
234
260
*/
235
261
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 ) {
240
264
slow = slow .next ;
241
265
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
+ }
251
274
}
252
- return p ;
275
+ return null ;
253
276
};
254
277
```
255
278
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
-
284
279
### ** ...**
285
280
286
281
```
0 commit comments