Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions 141. Linked List Cycle/note.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# step1

解法は

- slow/fast の2つのカーソルを使う方法
- 訪問済みノードを set で管理しておく方法
の2つが考えられる.

疑問点

- set には node を入れることができるか?その場合ハッシュ関数はどの様な実装になっているだろうか?Object の`__eq__`はどう実装されているだろうか.

前回は set を使用する方法で解いたので slow/fast で解いてみる.
time comlexity は O(N), space complexity は O(1).

# step2

見たコード, コメント

- google docs の sample answer
- reStructuredText という docstring の書き方を知った. こちらも命名スタイルと同様色々流派があることを把握して, 基礎的なものについては書けるようになるべき.
- while の条件文は head と head.next が None でないか確認している. 自分の回答だと head が None の場合早期 return しているが, この条件にするとまとめることができる.
- https://discord.com/channels/1084280443945353267/1195700948786491403/1195720397077880842
- 代入の仕方に選択の余地があることを確認. 理屈ではなく感覚でしかないが, 自分としては代入演算子が続くことは違和感を覚えるため分けている.
- wiki の cycle detection のページを見て, Floyd 以外にもバリエーションがあることを知った. 特に Brent のものは周期を高速に知ることができる. ただこの知識が常識に入るかどうかは怪しいと思うので, 高速である必要がある時以外は Floyd のアルゴリズムを選択するのが良いだろう.
- https://discord.com/channels/1084280443945353267/1192728121644945439/1192775334425272390
- 大域脱出に注意.
- https://discord.com/channels/1084280443945353267/1183683738635346001/1183690412926455868
- https://discord.com/channels/1084280443945353267/1200089668901937312/1205459051631222785
- Floyd のアルゴリズムにも while 前の初期化のバリエーションなどがあることを確認.

set には ListNode を入れることができる.

https://github.com/python/cpython/blob/main/Objects/classobject.c
ここに hash 関数や eq 関数が実装されていそうだが, 読めず.

実験したところ

```python
o = object()
p = object()
o.__eq__(p) # NotImplemented
```

という挙動. ちなみに hash の値は違った. leetcode で比較ができているのは, どこかで`__eq__`が実装されているからだと思う.

とおもったが, [この記事](https://blog.tiqwab.com/2017/02/26/implement-eq-in-python.html)によるとユーザー定義クラスの`__eq__`は id の比較を行うらしい.
18 changes: 18 additions & 0 deletions 141. Linked List Cycle/step1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None

class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
if not head:
return False
fast_cursor = head
slow_cursor = head
while fast_cursor.next and fast_cursor.next.next:
fast_cursor = fast_cursor.next.next
slow_cursor = slow_cursor.next
if fast_cursor == slow_cursor:
return True
return False
16 changes: 16 additions & 0 deletions 141. Linked List Cycle/step2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None

class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
fast_cursor = head
slow_cursor = head
while fast_cursor and fast_cursor.next:
fast_cursor = fast_cursor.next.next
slow_cursor = slow_cursor.next
if fast_cursor == slow_cursor:
return True
return False
17 changes: 17 additions & 0 deletions 141. Linked List Cycle/step3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None


class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
fast_cursor = head
slow_cursor = head
while fast_cursor and fast_cursor.next:
fast_cursor = fast_cursor.next.next
slow_cursor = slow_cursor.next
if fast_cursor == slow_cursor:
return True
return False