diff --git a/142. Linked List Cycle II.md b/142. Linked List Cycle II.md new file mode 100644 index 0000000..aa689fd --- /dev/null +++ b/142. Linked List Cycle II.md @@ -0,0 +1,87 @@ + +URL: https://leetcode.com/problems/linked-list-cycle-ii/description/ + +# Step 1 + +- 実装時間: 5分 +- 時間計算量: O(n) +- 空間計算量: O(n) +- フロイドのアルゴリズムでも解けると聞いた気がしたけど、理解してないので変数に記録する解放で解く。 + +```python +class Solution: + def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]: + node = head + nodes = set() + while node is not None: + if node in nodes: + return node + nodes.add(node) + node = node.next + return None +``` + +# Step 2 + +- `nodes`という変数名がいまいち。 + - すでに訪問済みであることを意味する`visited`にしよう。 + - Javaのクラスやフィールド名には一般的に名詞(句)なので、`visited_nodes`になる。 + - https://github.com/canisterism/leetcode/pull/3/files#r1688327425 + +- フロイドの循環検出の理解 + + - https://github.com/ichika0615/arai60/pull/2/files#r1807227628 + - `かめがスタート地点に戻った時、うさぎはどこにいるでしょうか。実は、うさぎは衝突点にいます。なぜかというと、うさぎは倍速で走っているからです。スタート地点から衝突点を通って衝突点に到達するうさぎルートの長さは、スタートから衝突点に到達するかめルートの2倍だからです。` + - ここちょっと混乱したので咀嚼してみる。 + - `スタート〜合流点`の距離はn(亀の歩いた距離だから) + - `スタート〜合流点`の距離は2n(うさぎの歩いた距離だから) + - ということは、「うさぎのいる位置(2n)」から、うさぎがn歩戻ると「スタートからの距離が2n-nの場所」にいる。つまり「亀の歩いた距離n」と等しく、すなわちそこは合流点。 + - setで解けることが常識の範囲 + - https://github.com/codgas/leetcode/pull/2/files#r1717036142 + +なにはともあれ、フロイドの循環検出も実装してみる。 + +- ヘルパー関数を使った方がわかりやすい気がした。 + +```python +class Solution: + def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]: + def find_meeting_point(head: Optional[ListNode]) -> Optional[ListNode]: + fast = head + slow = head + meeting_node = None + while fast is not None and fast.next is not None: + fast = fast.next.next + slow = slow.next + if slow == fast: + return slow + return None + + fast = find_meeting_point(head) + if fast is None: + return None + slow = head + while fast != slow: + fast = fast.next + slow = slow.next + return fast +``` + + +# Step 3 + +- 時間計算量: O(n) +- 空間計算量: O(n) + +```python +class Solution: + def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]: + node = head + visited = set() + while node is not None: + if node in visited: + return node + visited.add(node) + node = node.next + return None +```