From b96872e4b6e6252486dee462267ff3e0ec8346b8 Mon Sep 17 00:00:00 2001 From: TrsmYsk <53941356+TrsmYsk@users.noreply.github.com> Date: Wed, 24 Sep 2025 22:28:08 +0900 Subject: [PATCH] Create 141. Linked List Cycle.md --- .../141. Linked List Cycle.md | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 141. Linked List Cycle/141. Linked List Cycle.md diff --git a/141. Linked List Cycle/141. Linked List Cycle.md b/141. Linked List Cycle/141. Linked List Cycle.md new file mode 100644 index 0000000..db6b9d1 --- /dev/null +++ b/141. Linked List Cycle/141. Linked List Cycle.md @@ -0,0 +1,107 @@ +問題文: https://leetcode.com/problems/linked-list-cycle/description/ + +# step1: 何も見ないで考える +- 空間計算量がO(1)になる方法は思いつかなかったので、素直にsetを使った方法で書いた。 +- 今回の方法の時間計算量はO(n)、空間計算量はO(n)。 +- Noneはシングルトンだから判定に使う演算子は'=='でなく'is'である、という事実だけを特に理解せず記憶していたのでついでに理由を調べてみた。 + - 'is' はオブジェクトの同一性を判定するための演算子。 + - '==' は値の比較のための演算子で、x == y は x.__eq__(y) という特殊メソッドを呼び出している。 + - __eq__() はデフォルトだと is と同じだが、カスタマイズ可能。 + - シングルトンが何なのかよく分からなかったが、絶対に1個のインスタンスしか持たないオブジェクトみたいなものだと理解しておく。 + - 結局、Noneオブジェクトには絶対に1つしかインスタンスがないんだからオブジェクトの同一性をisで判定すれば十分、ということか。よくわからん。\ + https://docs.python.org/3.13/library/operator.html \ + https://docs.python.org/3.13/reference/datamodel.html#basic-customization +```python +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + checked_nodes = set() + node = head + if node is None: + return False + while node.next is not None: + if node in checked_nodes: + return True + checked_nodes.add(node) + node = node.next + return False + +``` + + +# step2: 他の人のレビューを参考にコードを整える +## setを使った方法 +- setの名前は visited_nodes や visited としている人が多かった。visited系の名前は連結リストの上を移動しているようなイメージがして処理を頭の中で描きやすい気がするので私も採用した。 +- 連結リストのnodeを調べるのは分かってるから、setの名前にnodesは入れなくてもいいという意見もあり、もっともなのでこちらも採用。 +```python +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + visited = set() + node = head + if node is None: + return False + while node.next is not None: + if node in visited: + return True + visited.add(node) + node = node.next + return False + +``` + +## フロイドの方法 +- 新井さんの解説動画で知った。通常人が初見で思いつける方法ではないと思ったのでDiscordの履歴を調べたら「科学手品」みたいなものということだったので一安心。\ + https://discord.com/channels/1084280443945353267/1195700948786491403/1195944696665604156 +- ループの条件で少し手こずったが、ウサギはノードを1つ飛ばして移動するので到着予定である2つ先のノードが存在してるかまでチェックすると整理した。 +```python +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + fast = head + slow = head + if fast is None: + return False + while fast.next is not None and fast.next.next is not None: + fast = fast.next.next + slow = slow.next + if fast is slow: + return True + return False + +``` + + +# step3: 10分以内にエラーを出さずに3回書く +## setを使った方法 +```python +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + visited = set() + node = head + if node is None: + return False + while node.next is not None: + if node in visited: + return True + visited.add(node) + node = node.next + return False + +``` + +## フロイドの方法 +```python +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + fast = head + slow = head + if fast is None: + return False + while fast.next is not None and fast.next.next is not None: + fast = fast.next.next + slow = slow.next + if fast is slow: + return True + return False + +``` + +次の問題: 142. Linked List Cycle II ( https://leetcode.com/problems/linked-list-cycle-ii/description/ )