|
64 | 64 |
|
65 | 65 | ### 方法一:哈希表
|
66 | 66 |
|
67 |
| -遍历链表,并使用哈希表记录每个节点。当某个节点二次出现时,则表示存在环,直接返回 `true`。否则链表遍历结束,返回 `false`。 |
| 67 | +我们可以遍历链表,用一个哈希表 $s$ 记录每个节点。当某个节点二次出现时,则表示存在环,直接返回 `true`。否则链表遍历结束,返回 `false`。 |
68 | 68 |
|
69 | 69 | 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是链表中的节点数。
|
70 | 70 |
|
|
78 | 78 | # self.next = None
|
79 | 79 |
|
80 | 80 |
|
| 81 | +class Solution: |
| 82 | + def hasCycle(self, head: Optional[ListNode]) -> bool: |
| 83 | + s = set() |
| 84 | + while head: |
| 85 | + if head in s: |
| 86 | + return True |
| 87 | + s.add(head) |
| 88 | + head = head.next |
| 89 | + return False |
| 90 | +``` |
| 91 | + |
| 92 | +```java |
| 93 | +/** |
| 94 | + * Definition for singly-linked list. |
| 95 | + * class ListNode { |
| 96 | + * int val; |
| 97 | + * ListNode next; |
| 98 | + * ListNode(int x) { |
| 99 | + * val = x; |
| 100 | + * next = null; |
| 101 | + * } |
| 102 | + * } |
| 103 | + */ |
| 104 | +public class Solution { |
| 105 | + public boolean hasCycle(ListNode head) { |
| 106 | + Set<ListNode> s = new HashSet<>(); |
| 107 | + for (; head != null; head = head.next) { |
| 108 | + if (!s.add(head)) { |
| 109 | + return true; |
| 110 | + } |
| 111 | + } |
| 112 | + return false; |
| 113 | + } |
| 114 | +} |
| 115 | +``` |
| 116 | + |
| 117 | +```cpp |
| 118 | +/** |
| 119 | + * Definition for singly-linked list. |
| 120 | + * struct ListNode { |
| 121 | + * int val; |
| 122 | + * ListNode *next; |
| 123 | + * ListNode(int x) : val(x), next(NULL) {} |
| 124 | + * }; |
| 125 | + */ |
| 126 | +class Solution { |
| 127 | +public: |
| 128 | + bool hasCycle(ListNode* head) { |
| 129 | + unordered_set<ListNode*> s; |
| 130 | + for (; head; head = head->next) { |
| 131 | + if (s.contains(head)) { |
| 132 | + return true; |
| 133 | + } |
| 134 | + s.insert(head); |
| 135 | + } |
| 136 | + return false; |
| 137 | + } |
| 138 | +}; |
| 139 | +``` |
| 140 | +
|
| 141 | +```go |
| 142 | +/** |
| 143 | + * Definition for singly-linked list. |
| 144 | + * type ListNode struct { |
| 145 | + * Val int |
| 146 | + * Next *ListNode |
| 147 | + * } |
| 148 | + */ |
| 149 | +func hasCycle(head *ListNode) bool { |
| 150 | + s := map[*ListNode]bool{} |
| 151 | + for ; head != nil; head = head.Next { |
| 152 | + if s[head] { |
| 153 | + return true |
| 154 | + } |
| 155 | + s[head] = true |
| 156 | + } |
| 157 | + return false |
| 158 | +} |
| 159 | +``` |
| 160 | + |
| 161 | +```ts |
| 162 | +/** |
| 163 | + * Definition for singly-linked list. |
| 164 | + * class ListNode { |
| 165 | + * val: number |
| 166 | + * next: ListNode | null |
| 167 | + * constructor(val?: number, next?: ListNode | null) { |
| 168 | + * this.val = (val===undefined ? 0 : val) |
| 169 | + * this.next = (next===undefined ? null : next) |
| 170 | + * } |
| 171 | + * } |
| 172 | + */ |
| 173 | + |
| 174 | +function hasCycle(head: ListNode | null): boolean { |
| 175 | + const s: Set<ListNode> = new Set(); |
| 176 | + for (; head; head = head.next) { |
| 177 | + if (s.has(head)) { |
| 178 | + return true; |
| 179 | + } |
| 180 | + s.add(head); |
| 181 | + } |
| 182 | + return false; |
| 183 | +} |
| 184 | +``` |
| 185 | + |
| 186 | +<!-- tabs:end --> |
| 187 | + |
| 188 | +### 方法二:快慢指针 |
| 189 | + |
| 190 | +我们定义快慢指针 $fast$ 和 $slow$,初始时均指向 $head$。 |
| 191 | + |
| 192 | +快指针每次走两步,慢指针每次走一步,不断循环。当快慢指针相遇时,说明链表存在环。如果循环结束依然没有相遇,说明链表不存在环。 |
| 193 | + |
| 194 | +时间复杂度 $O(n)$,其中 $n$ 是链表中的节点数。空间复杂度 $O(1)$。 |
| 195 | + |
| 196 | +<!-- tabs:start --> |
| 197 | + |
| 198 | +```python |
| 199 | +# Definition for singly-linked list. |
| 200 | +# class ListNode: |
| 201 | +# def __init__(self, x): |
| 202 | +# self.val = x |
| 203 | +# self.next = None |
| 204 | + |
| 205 | + |
81 | 206 | class Solution:
|
82 | 207 | def hasCycle(self, head: ListNode) -> bool:
|
83 | 208 | slow = fast = head
|
@@ -176,14 +301,14 @@ func hasCycle(head *ListNode) bool {
|
176 | 301 | */
|
177 | 302 |
|
178 | 303 | function hasCycle(head: ListNode | null): boolean {
|
179 |
| - const set = new Set<ListNode>(); |
180 |
| - let node = head; |
181 |
| - while (node !== null) { |
182 |
| - if (set.has(node)) { |
| 304 | + let slow = head; |
| 305 | + let fast = head; |
| 306 | + while (fast !== null && fast.next !== null) { |
| 307 | + slow = slow.next; |
| 308 | + fast = fast.next.next; |
| 309 | + if (slow === fast) { |
183 | 310 | return true;
|
184 | 311 | }
|
185 |
| - set.add(node); |
186 |
| - node = node.next; |
187 | 312 | }
|
188 | 313 | return false;
|
189 | 314 | }
|
@@ -246,43 +371,4 @@ public class Solution {
|
246 | 371 |
|
247 | 372 | <!-- tabs:end -->
|
248 | 373 |
|
249 |
| -### 方法二:快慢指针 |
250 |
| - |
251 |
| -我们定义快慢指针 $fast$ 和 $slow$,初始时均指向 $head$。 |
252 |
| - |
253 |
| -快指针每次走两步,慢指针每次走一步,不断循环。当快慢指针相遇时,说明链表存在环。如果循环结束依然没有相遇,说明链表不存在环。 |
254 |
| - |
255 |
| -时间复杂度 $O(n)$,其中 $n$ 是链表中的节点数。空间复杂度 $O(1)$。 |
256 |
| - |
257 |
| -<!-- tabs:start --> |
258 |
| - |
259 |
| -```ts |
260 |
| -/** |
261 |
| - * Definition for singly-linked list. |
262 |
| - * class ListNode { |
263 |
| - * val: number |
264 |
| - * next: ListNode | null |
265 |
| - * constructor(val?: number, next?: ListNode | null) { |
266 |
| - * this.val = (val===undefined ? 0 : val) |
267 |
| - * this.next = (next===undefined ? null : next) |
268 |
| - * } |
269 |
| - * } |
270 |
| - */ |
271 |
| - |
272 |
| -function hasCycle(head: ListNode | null): boolean { |
273 |
| - let slow = head; |
274 |
| - let fast = head; |
275 |
| - while (fast !== null && fast.next !== null) { |
276 |
| - slow = slow.next; |
277 |
| - fast = fast.next.next; |
278 |
| - if (slow === fast) { |
279 |
| - return true; |
280 |
| - } |
281 |
| - } |
282 |
| - return false; |
283 |
| -} |
284 |
| -``` |
285 |
| - |
286 |
| -<!-- tabs:end --> |
287 |
| - |
288 | 374 | <!-- end -->
|
0 commit comments