Skip to content

Conversation

yosukekato165
Copy link
Owner

@yosukekato165 yosukekato165 commented Aug 19, 2025

@yosukekato165 yosukekato165 self-assigned this Aug 19, 2025
5分以内にはまったく解けなかった。
なんとなく一度訪れた値を保存しておいて、再度訪れたら true を返すイメージだけ思いついたが、表現方法が分からずタイムアウト。

調べると自分がイメージしていたのは、再帰関数で実現出来そうだったので、再帰関数で対応してみた。
Copy link

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

最終的には、どのやりかたもいいところ悪いところがあるが、その中ではこれが今のところよいかなと思えるようになることです。

Copy link
Owner Author

@yosukekato165 yosukekato165 Aug 24, 2025

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での再帰は現実的ではないのかな?と思いました。

https://www.reddit.com/r/leetcode/comments/12xy7f9/extraordinarily_high_system_recursion_limit_for/?tl=ja

Comment on lines +7 to +18
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())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

たしかに再帰で書けますね。思いつかなかったので、おもしろいな〜と思いました。

5分以内にはまったく解けなかった。
なんとなく一度訪れた値を保存しておいて、再度訪れたら true を返すイメージだけ思いついたが、表現方法が分からずタイムアウト。

調べると自分がイメージしていたのは、再帰関数で実現出来そうだったので、再帰関数で対応してみた。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

何を見たか、リファレンスへのリンクがあると比較しやすいかなと思いました。

Copy link
Owner Author

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:

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

Copy link
Owner Author

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:

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 != fastslow.__ne__(fast)の構文糖であり、TreeNodeにそのspecial methodが定義されていなければ、is notと同じ結果が返るのですが、TreeNodeに__ne__()の定義があった場合、この条件式が予期せぬ値を返すことが予想されます。LeetCodeのTreeNodeの定義では大丈夫なのですが、is notだと読み手にこのようなことを心配させないメリットがあります。

Copy link
Owner Author

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):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inner function とするなら、visited は引数に取らず、hasCycle のスコープで定義すればよいと思います

Copy link
Owner Author

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):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

手法を関数名にすることはあまりないので、has_cycle_helper などの命名が無難かなと思います。

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ryosuketc
手法を関数名にすることはないんですね!
アルゴリズムを学習するのが初めてなので知らない人にも分かりやすいかなぁと思ったんですが、
「常識として知っているべきだから手法を明示する必要はない」と言うことなのでしょうか?
それとも手法は別の方法で明示するべきなのでしょうか?
d65d37d

Copy link

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)

これ想像がつきますね。
https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0#heading=h.fcs3httrll4l

Copy link
Owner Author

@yosukekato165 yosukekato165 Aug 24, 2025

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):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これは再帰ではないですね

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ryosuketc
本当ですね、、
再帰とループに混乱していました。
コメントありがとうございます!
d65d37d

return True
visited.add(node)
node = node.next
return False
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ファイルの末尾が開業で終わっていないことを示す警告が出ているようです。ファイルの末尾は改行で終えることをおすすめします。

Copy link
Owner Author

@yosukekato165 yosukekato165 Aug 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nodchip
コメントありがとうございます!
修正しました!
b743866

Copy link

@huyfififi huyfififi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@@ -4,18 +4,7 @@
# self.val = x
# self.next = None

class Solution(object):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

後から指摘された点や修正した場所を見返すのに役立つので、この勉強会では指摘のあったコードはそのままにしておくのがオススメですね。

Copy link
Owner Author

@yosukekato165 yosukekato165 Aug 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@huyfififi
コメントありがとうございます!
最後のPRで不要なファイルのコミットや修正の巻き戻しが発生していたようなので修正いたしました!
2a5b8bf

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>

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

Copy link
Owner Author

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:
Copy link

@huyfififi huyfififi Aug 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

broodさんがご指摘の通り、また私のa != ba.__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

Copy link
Owner Author

@yosukekato165 yosukekato165 Aug 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@huyfififi

ここでしたいのはListNodeの真偽値チェックではなく、Noneではないかチェックであると思います、!= 同様 ListNode の定義次第ではこの条件式が予期せぬ挙動をするので。

コメントありがとうございます!
確かにです!

定義次第ではこの条件式が予期せぬ挙動をするので。

この「定義次第で条件式が予期せぬ挙動をする」部分が普段意識出来ておらず抜けがちなようです!
これから意識していこうと思います!

dd7b06a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants