diff --git a/141. Linked List Cycle.md b/141. Linked List Cycle.md new file mode 100644 index 0000000..2d998e1 --- /dev/null +++ b/141. Linked List Cycle.md @@ -0,0 +1,82 @@ + +URL: https://leetcode.com/problems/linked-list-cycle/description/ + +# Step 1 + +- 実装時間: 5分 +- 時間計算量: O(n) +- 空間計算量: O(1) +- Fast-Slowという単語を聞いたことがあったので、思い出しながら5分ほどで実装。 +- 空のリストのケースを考慮できておらず一度NGとなった。 + +```python +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + fast, slow = head, head + while fast is not None and fast.next is not None and fast.next.next is not None: + fast = fast.next.next + slow = slow.next + if fast == slow: + return True + return False +``` + +# Step 2 + +- 代入のスタイルの一貫性がないことに気づいた。「多重代入」か「それぞれ代入する」か。今回は、「それぞれ代入する」に統一する。 +- ループ条件のfast.next.nextは確認する意味がないことに気づいたので、削除。 +- Noneじゃないことのチェックに、`is not None`のチェックは不要なので削除。 + - 参考:https://docs.python.org/3/library/stdtypes.html#truth-value-testing + +```python +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + fast = head + slow = head + while fast and fast.next: + fast = fast.next.next + slow = slow.next + if fast == slow: + return True + return False +``` + +- サンプル回答を見ていて別解を見つけた。こっちの方が優れていると感じた。 + - fast-slowというアイデアを使わずに、訪問済みのNodeをチェックする素直な実装。 +- デメリット + - visitedが大きくなるので、空間計算量がO(n)となる。 + - `if curr in visited:`で時間計算量O(n)のチェックが必要。 + +```python +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + visited = set() + + curr = head + + while curr: + if curr in visited: + return True + visited.add(curr) + curr = curr.next + + return False +``` + +# Step 3 + +- 時間計算量: O(n) +- 空間計算量: O(n) + +```python +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + visited = set() + cur = head + while cur: + if cur in visited: + return True + visited.add(cur) + cur = cur.next + return False +```