10
10
11
11
## 解法
12
12
13
- ### 方法一
13
+ ### 方法一:快慢指针
14
+
15
+ 我们先利用快慢指针判断链表是否有环,如果有环的话,快慢指针一定会相遇,且相遇的节点一定在环中。
16
+
17
+ 如果没有环,快指针会先到达链表尾部,直接返回 ` null ` 即可。
18
+
19
+ 如果有环,我们再定义一个答案指针 $ans$ 指向链表头部,然后让 $ans$ 和慢指针一起向前走,每次走一步,直到 $ans$ 和慢指针相遇,相遇的节点即为环的入口节点。
20
+
21
+ 为什么这样能找到环的入口节点呢?
22
+
23
+ 我们不妨假设链表头节点到环入口的距离为 $x$,环入口到相遇节点的距离为 $y$,相遇节点到环入口的距离为 $z$,那么慢指针走过的距离为 $x + y$,快指针走过的距离为 $x + y + k \times (y + z)$,其中 $k$ 是快指针在环中绕了 $k$ 圈。
24
+
25
+ <p ><img src =" https://fastly.jsdelivr.net/gh/doocs/leetcode@main/lcci/02.08.Linked%20List%20Cycle/images/linked-list-cycle-ii.png " /></p >
26
+
27
+ 由于快指针速度是慢指针的 $2$ 倍,因此有 $2 \times (x + y) = x + y + k \times (y + z)$,可以推出 $x + y = k \times (y + z)$,即 $x = (k - 1) \times (y + z) + z$。
28
+
29
+ 也即是说,如果我们定义一个答案指针 $ans$ 指向链表头部,然后 $ans$ 和慢指针一起向前走,那么它们一定会在环入口相遇。
30
+
31
+ 时间复杂度 $O(n)$,其中 $n$ 是链表中节点的数目。空间复杂度 $O(1)$。
14
32
15
33
<!-- tabs:start -->
16
34
23
41
24
42
25
43
class Solution :
26
- def detectCycle (self , head : ListNode) -> ListNode:
27
- slow = fast = head
28
- has_cycle = False
29
- while not has_cycle and fast and fast.next:
30
- slow, fast = slow.next, fast.next.next
31
- has_cycle = slow == fast
32
- if not has_cycle:
33
- return None
34
- p = head
35
- while p != slow:
36
- p, slow = p.next, slow.next
37
- return p
44
+ def detectCycle (self , head : Optional[ListNode]) -> Optional[ListNode]:
45
+ fast = slow = head
46
+ while fast and fast.next:
47
+ slow = slow.next
48
+ fast = fast.next.next
49
+ if slow == fast:
50
+ ans = head
51
+ while ans != slow:
52
+ ans = ans.next
53
+ slow = slow.next
54
+ return ans
38
55
```
39
56
40
57
``` java
@@ -51,22 +68,20 @@ class Solution:
51
68
*/
52
69
public class Solution {
53
70
public ListNode detectCycle (ListNode head ) {
54
- ListNode slow = head, fast = head;
55
- boolean hasCycle = false ;
56
- while (! hasCycle && fast != null && fast. next != null ) {
71
+ ListNode fast = head, slow = head;
72
+ while (fast != null && fast. next != null ) {
57
73
slow = slow. next;
58
74
fast = fast. next. next;
59
- hasCycle = slow == fast;
75
+ if (slow == fast) {
76
+ ListNode ans = head;
77
+ while (ans != slow) {
78
+ ans = ans. next;
79
+ slow = slow. next;
80
+ }
81
+ return ans;
82
+ }
60
83
}
61
- if (! hasCycle) {
62
- return null ;
63
- }
64
- ListNode p = head;
65
- while (p != slow) {
66
- p = p. next;
67
- slow = slow. next;
68
- }
69
- return p;
84
+ return null ;
70
85
}
71
86
}
72
87
```
@@ -83,23 +98,21 @@ public class Solution {
83
98
class Solution {
84
99
public:
85
100
ListNode* detectCycle(ListNode* head) {
86
- ListNode* slow = head;
87
101
ListNode* fast = head;
88
- bool hasCycle = false ;
89
- while (!hasCycle && fast && fast->next) {
102
+ ListNode * slow = head ;
103
+ while (fast && fast->next) {
90
104
slow = slow->next;
91
105
fast = fast->next->next;
92
- hasCycle = slow == fast;
93
- }
94
- if (!hasCycle) {
95
- return nullptr;
106
+ if (slow == fast) {
107
+ ListNode* ans = head;
108
+ while (ans != slow) {
109
+ ans = ans->next;
110
+ slow = slow->next;
111
+ }
112
+ return ans;
113
+ }
96
114
}
97
- ListNode* p = head;
98
- while (p != slow) {
99
- p = p->next;
100
- slow = slow->next;
101
- }
102
- return p;
115
+ return nullptr;
103
116
}
104
117
};
105
118
```
@@ -113,20 +126,51 @@ public:
113
126
* }
114
127
*/
115
128
func detectCycle(head *ListNode) *ListNode {
116
- slow, fast := head, head
117
- hasCycle := false
118
- for !hasCycle && fast != nil && fast.Next != nil {
119
- slow, fast = slow.Next, fast.Next.Next
120
- hasCycle = slow == fast
121
- }
122
- if !hasCycle {
123
- return nil
129
+ fast, slow := head, head
130
+ for fast != nil && fast.Next != nil {
131
+ slow = slow.Next
132
+ fast = fast.Next.Next
133
+ if slow == fast {
134
+ ans := head
135
+ for ans != slow {
136
+ ans = ans.Next
137
+ slow = slow.Next
138
+ }
139
+ return ans
140
+ }
124
141
}
125
- p := head
126
- for p != slow {
127
- p, slow = p.Next, slow.Next
128
- }
129
- return p
142
+ return nil
143
+ }
144
+ ```
145
+
146
+ ``` ts
147
+ /**
148
+ * Definition for singly-linked list.
149
+ * class ListNode {
150
+ * val: number
151
+ * next: ListNode | null
152
+ * constructor(val?: number, next?: ListNode | null) {
153
+ * this.val = (val===undefined ? 0 : val)
154
+ * this.next = (next===undefined ? null : next)
155
+ * }
156
+ * }
157
+ */
158
+
159
+ function detectCycle(head : ListNode | null ): ListNode | null {
160
+ let [slow, fast] = [head , head ];
161
+ while (fast && fast .next ) {
162
+ slow = slow .next ;
163
+ fast = fast .next .next ;
164
+ if (slow === fast ) {
165
+ let ans = head ;
166
+ while (ans !== slow ) {
167
+ ans = ans .next ;
168
+ slow = slow .next ;
169
+ }
170
+ return ans ;
171
+ }
172
+ }
173
+ return null ;
130
174
}
131
175
```
132
176
@@ -144,26 +188,19 @@ func detectCycle(head *ListNode) *ListNode {
144
188
* @return {ListNode}
145
189
*/
146
190
var detectCycle = function (head ) {
147
- let slow = head;
148
- let fast = head;
149
- let hasCycle = false ;
150
- while (! hasCycle && fast && fast .next ) {
191
+ let [slow, fast] = [head, head];
192
+ while (fast && fast .next ) {
151
193
slow = slow .next ;
152
194
fast = fast .next .next ;
153
- hasCycle = slow == fast;
154
- }
155
- if (! hasCycle) {
156
- return null ;
157
- }
158
- let p = head;
159
- while (p != slow) {
160
- p = p .next ;
161
- slow = slow .next ;
195
+ if (slow === fast) {
196
+ let ans = head;
197
+ while (ans !== slow) {
198
+ ans = ans .next ;
199
+ slow = slow .next ;
200
+ }
201
+ return ans;
202
+ }
162
203
}
163
- return p ;
204
+ return null ;
164
205
};
165
206
```
166
-
167
- <!-- tabs: end -->
168
-
169
- <!-- end -->
0 commit comments