-
Notifications
You must be signed in to change notification settings - Fork 0
141. Linked List Cycle #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
5分以内にはまったく解けなかった。 | ||
なんとなく一度訪れた値を保存しておいて、再度訪れたら true を返すイメージだけ思いついたが、表現方法が分からずタイムアウト。 | ||
|
||
調べると自分がイメージしていたのは、再帰関数で実現出来そうだったので、再帰関数で対応してみた。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
再帰で書くことはとてもよいことですが、再帰は深さの限界があることが多いので状況からして問題がないかを見積もりましょう。
もちろん、他にもいろいろなよしあしがあるので徐々に意識していきましょう。
https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0#heading=h.uvguf4c3q02d
最終的には、どのやりかたもいいところ悪いところがあるが、その中ではこれが今のところよいかなと思えるようになることです。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@oda
コメントありがとうございます!
LeetCode 141: Linked List Cycle の制約
- ノード数: 0 ≤ n ≤ 10^4
- 最悪ケース: 10,000ノードの一直線リスト
上記の場合は深さは最大O(10^4)になる認識です。
調べたところ、leetcodeの深さは最大550000まで大丈夫なようなのでleetcode上では大丈夫そうですが、
ローカルのMacの場合1000が限界と言う内容もあるのでptyhonでの再帰は現実的ではないのかな?と思いました。
class Solution(object): | ||
def hasCycle(self, head): | ||
def depthFirstSearch(node, visited): | ||
if not node: | ||
return False | ||
if node in visited: | ||
return True | ||
|
||
visited.add(node) | ||
return depthFirstSearch(node.next, visited) | ||
|
||
return depthFirstSearch(head, set()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
たしかに再帰で書けますね。思いつかなかったので、おもしろいな〜と思いました。
5分以内にはまったく解けなかった。 | ||
なんとなく一度訪れた値を保存しておいて、再度訪れたら true を返すイメージだけ思いついたが、表現方法が分からずタイムアウト。 | ||
|
||
調べると自分がイメージしていたのは、再帰関数で実現出来そうだったので、再帰関数で対応してみた。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
何を見たか、リファレンスへのリンクがあると比較しやすいかなと思いました。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brood0783
コメントありがとうございます!!
今回はAIに聞いて出てきたものだったので次からリンク共有出来るようにします!
fast = head.next | ||
|
||
while slow != fast: | ||
if not fast or not fast.next: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
notはfalsy判定なので、is Noneの方が安全かなと思いました。
https://stackoverflow.com/questions/39983695/what-is-truthy-and-falsy-how-is-it-different-from-true-and-false
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brood0783
not が falsy 判定だったんですね!修正しました!
d65d37d
slow = head | ||
fast = head.next | ||
|
||
while slow != fast: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
今回の場合、==
や!=
で確認される値の等価性ではなく、slowとfastが同じオブジェクトを指しているかどうかをチェックしたいので、slow is not fast
の方が適切かと思います。
slow != fast
はslow.__ne__(fast)
の構文糖であり、TreeNodeにそのspecial methodが定義されていなければ、is not
と同じ結果が返るのですが、TreeNodeに__ne__()
の定義があった場合、この条件式が予期せぬ値を返すことが予想されます。LeetCodeのTreeNodeの定義では大丈夫なのですが、is not
だと読み手にこのようなことを心配させないメリットがあります。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@huyfififi
コメントありがとうございます!
!=
がslow.__ne__(fast)
の構文糖であるのは驚きでした!
普段TypeScriptを書いているので当たり前のように使用していたのですが、Ptyhonでは構文糖であり書き換えが可能なんだと理解しました!
d65d37d
|
||
class Solution(object): | ||
def hasCycle(self, head): | ||
def depthFirstSearch(node, visited): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inner function とするなら、visited
は引数に取らず、hasCycle
のスコープで定義すればよいと思います
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ryosuketc
コメントありがとうございます!
確かにです!
出来るだけ純粋関数にしたかったんですが、inner function であれば関係ありませんでした。
d65d37d
|
||
class Solution(object): | ||
def hasCycle(self, head): | ||
def depthFirstSearch(node, visited): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
手法を関数名にすることはあまりないので、has_cycle_helper
などの命名が無難かなと思います。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ryosuketc
手法を関数名にすることはないんですね!
アルゴリズムを学習するのが初めてなので知らない人にも分かりやすいかなぁと思ったんですが、
「常識として知っているべきだから手法を明示する必要はない」と言うことなのでしょうか?
それとも手法は別の方法で明示するべきなのでしょうか?
d65d37d
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
書類の整理のときにフォルダーに書く名前は「平成25年度取締役会議事録」などであって、中の構造、たとえば「時系列順」ではないですよね。
関数の名前は、呼んでいるときに中身を見ずに、入力から何が出てくるかが分かるといいです。
student_names = recursion(student_names)
こう書いてあったら recursion の中を解読に行きますね。探索が一段階で済めばいいですけど。
student_names = sorted(student_names)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@oda
コメントありがとうございます!
関数の名前は、呼んでいるときに中身を見ずに、入力から何が出てくるかが分かるといいです。
確かにです!
関数を使う側としては、内部の処理よりも何を返してもらえるか。の方が重要ですね!
でないと、内部の処理を読んでからでないと必要な値を返してくれるか判断つかずコードリーディングに時間掛かりますし、何よりストレスが凄そうだなぁと思いました!
|
||
return True | ||
|
||
class RecursionSolution(object): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
これは再帰ではないですね
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ryosuketc
本当ですね、、
再帰とループに混乱していました。
コメントありがとうございます!
d65d37d
arai60/linked-list-cycle/step2.py
Outdated
return True | ||
visited.add(node) | ||
node = node.next | ||
return False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ファイルの末尾が開業で終わっていないことを示す警告が出ているようです。ファイルの末尾は改行で終えることをおすすめします。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
arai60/linked-list-cycle/step1.py
Outdated
@@ -4,18 +4,7 @@ | |||
# self.val = x | |||
# self.next = None | |||
|
|||
class Solution(object): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
後から指摘された点や修正した場所を見返すのに役立つので、この勉強会では指摘のあったコードはそのままにしておくのがオススメですね。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@huyfififi
コメントありがとうございます!
最後のPRで不要なファイルのコミットや修正の巻き戻しが発生していたようなので修正いたしました!
2a5b8bf
.idea/LeetCode.iml
Outdated
@@ -0,0 +1,11 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
あまりこれらのファイルに明るくないのですが、この問題に関連するコードではなくエディタの設定のように見受けられるので、PRには含めない方が(先にmainにpushしておくか.gitignoreを設定しておく)レビューしやすくなると思います。また、エディタの設定でinsert final new lineのような設定を有効化しておくことをオススメします。
参考: https://stackoverflow.com/questions/729692/why-should-text-files-end-with-a-newline
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@huyfififi
こちらも上記と同じく途中で入り込んでしまっていたので削除しました!
2a5b8bf
また、vscodeに一旦切り替えたのでそちらで insert final new line 設定追加しました!
insert final new lineの設定があることすら知らなかたので教えて頂きありがとうございます!!
https://qiita.com/kyo_nanba/items/d384b2a46170bf8764dd
def hasCycle(self, head): | ||
visited = set() | ||
node = head | ||
while node: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
broodさんがご指摘の通り、また私のa != b
はa.__ne__(b)
であるというコメントも合わせて、私はwhile node is not None:
の方が適切かと思っています。ここでしたいのはListNodeの真偽値チェックではなく、Noneではないかチェックであると思いますし、!=
同様 ListNode
の定義次第ではこの条件式が予期せぬ挙動をするので。
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
def __bool__(self):
return self.val > 0
if ListNode(1):
print(bool(ListNode(1))) # True
if not ListNode(0):
print(bool(ListNode(0))) # False
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ここでしたいのはListNodeの真偽値チェックではなく、Noneではないかチェックであると思います、!= 同様 ListNode の定義次第ではこの条件式が予期せぬ挙動をするので。
コメントありがとうございます!
確かにです!
定義次第ではこの条件式が予期せぬ挙動をするので。
この「定義次第で条件式が予期せぬ挙動をする」部分が普段意識出来ておらず抜けがちなようです!
これから意識していこうと思います!
https://leetcode.com/problems/linked-list-cycle/
Next: https://leetcode.com/problems/linked-list-cycle-ii/