01. Linked List Cycle
読了目安 約2分
Linked List / LeetCode 141 (Easy) — 連結リストに循環があるかを速さの違う 2 つのポインタで判定する。
この章の目次
問題
LeetCode 141. Linked List Cycle(Easy / カテゴリ: Linked List)
連結リストは、各ノードが値と「次のノードへの参照」を持つデータ構造です。
その先頭ノード head が与えられます。
next をたどり続けるとどこかのノードへ戻ってくる(循環がある)とき true を、末尾の nil に到達するとき false を返してください。
考え方
ヒント 1
一度訪れたノードをすべて覚えておくと、同じノードに 2 回目に到達した時点で循環だと分かります。 まずはこの方針で考えてみてください。
ヒント 2
追加のメモリなしで解くには、1 歩ずつ進む遅いポインタと 2 歩ずつ進む速いポインタを同時に走らせます。
循環があれば速い方がいつか遅い方に追いつき、なければ速い方が先に nil へ到達します。
Swift 実装のポイント
ListNodeはclassで定義します。ノードどうしを参照でつなぐため、値型のstructでは表現できません。- 同じノードかどうかは
===(参照の同一性)で比べます。ListNodeはEquatableではないので==は使えません。 - ループ条件は
fast != nil && fast?.next != nilのように、オプショナルの nil 判定で書きます。
模範解答
class Solution {
func hasCycle(_ head: ListNode?) -> Bool {
var slow = head
var fast = head
while fast != nil && fast?.next != nil {
slow = slow?.next
fast = fast?.next?.next
if slow === fast {
return true
}
}
return false
}
}計算量: O(n) 時間、O(1) 追加メモリ。