Skip to content

0141. linked list cycle #1

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

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open

0141. linked list cycle #1

wants to merge 10 commits into from

Conversation

ryo-devz
Copy link
Owner

@ryo-devz ryo-devz commented Aug 7, 2024

問題: 141. Linked List Cycle

https://leetcode.com/problems/linked-list-cycle/description/

言語: Python


class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
if head is None or head.next is None:
Copy link

Choose a reason for hiding this comment

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

head.next is Noneはなくても大丈夫だと思います

Copy link
Owner Author

Choose a reason for hiding this comment

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

以下のループの箇所でhead.next is Noneの場合ループを抜けるので上記のif文のhead.next is Noneは不要と理解しました。
そういう意味だとhead is Noneも以下の処理に含まれているので不要な気もしてきました。。

while head:

- XXX
-
- Linked Listとは?
- ノードの値と次の要素の参照を持っているデータの構造体。配列と比較してデータの挿入と削除が可能。
Copy link

Choose a reason for hiding this comment

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

「配列と比較してデータの挿入と削除が可能。」の部分がよくわからなかったのですが、固定長配列の話をしていますか?確かに固定長配列の場合、サイズを変えようとしたら新たにメモリを確保してそこに要素をコピーする必要があると思うのですが、そういう意味でデータの挿入と削除ができないということでしょうか?

他にも配列とはそもそも何なのか、動的配列、Pythonのリストの内部の仕組み、配列/連結リストの末尾や真ん中への要素の追加・削除の時間計算量などを調べてみるといいと思います

Copy link
Owner Author

Choose a reason for hiding this comment

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

浅い知識で深掘りできてなかったので、あまり深い意味はなくメモ書きしてしまってました。。
もう少し記載いただいた内容のあたりを調べてみようと思います!

while head:
if head.val == "*":
return True
head.val = "*"
Copy link

@goto-untrapped goto-untrapped Aug 8, 2024

Choose a reason for hiding this comment

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

入力を破壊して求めるやり方もできますし、入力を破壊しないで求めるやり方もできそうですよね。

Copy link

Choose a reason for hiding this comment

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

"" に特別な意味をつける方法は、""を別の人が別の特別な意味をつけると破綻しますので、デメリットが大きいのでそのデメリットに見合うものでなかったら避けましょう。また、None などのほうが特別の意味をもたせることのデメリットが小さめです。あと、入力を破壊していいかは状況次第ですのでそれも別途考えましょう。

Copy link
Owner Author

@ryo-devz ryo-devz Aug 9, 2024

Choose a reason for hiding this comment

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

ありがとうございます。確かに自分ルールで特別な意味を持たせると、他の人が別の意味を持たせてしまうと破綻するので非推奨に思えますね、、Noneなどの予約語で特別な意味を持たせることはまたメリットデメリットの度合いが異なりそうですね。。新しい観点で勉強になりますm(_ _)m

また、入力を破壊するというところはもう少し意識して実装したいと思います。
入力を破壊した実装をすると以下のようなことが起きてしまうので引き数を破壊せず実装する方がより良いのではないかと個人的には思いました!

  • 引き数が想定外の値に変わってしまうのでその引き数を利用する際に想定外の挙動が起きる
  • 特別な意味を持たせた値があったとして、その値をたまたまもともとList内に持っていた場合に破綻する

fast = fast.next.next
if slow == fast:
return True
return False

Choose a reason for hiding this comment

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

汎用的な方法として使えそうという意味合いで、1st_step.py のようなやり方いいですね。

Copy link
Owner Author

@ryo-devz ryo-devz Aug 9, 2024

Choose a reason for hiding this comment

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

ありがとうございます。若干力業感は否めないですが・・かつstep2以降は知ってる人が解けるアルゴリズムのようなのでよりそのように感じるのかも知れないですね。。
今後、汎用的に利用できるかという視点を持って実装したいと思います!

if head.val == "*":
return True
head.val = "*"
head = head.next
Copy link

Choose a reason for hiding this comment

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

head は通常連結リストの先頭のノードを表すそうなので、別の変数名にした方が良いかもしれません。
h1rosaka/arai60#2 (comment)

Copy link
Owner Author

Choose a reason for hiding this comment

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

ありがとうございます。agreeです。headを動かすとheadじゃないやん!ってなりますもんね。。
こういった場合は別の変数名にしようと思います!

def hasCycle(self, head: Optional[ListNode]) -> bool:
if head is None or head.next is None:
return False
while head:
Copy link

Choose a reason for hiding this comment

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

while head is not None の方がPEP8的にはおすすめのようでした。

None のようなシングルトンと比較をする場合は、常に is か is not を使うべきです。絶対に等値演算子を使わないでください。また、 本当は if x is not None と書いているつもりで、 if x と書いている場合は注意してください - たとえば、デフォルトの値がNoneになる変数や引数に、何かしら別の値が設定されているかどうかをテストする場合です。この「別の値」は、ブール型のコンテクストでは False と評価される(コンテナのような)型かもしれませんよ!

https://pep8-ja.readthedocs.io/ja/latest/#section-36

Copy link
Owner Author

Choose a reason for hiding this comment

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

なるほど、、今の書き方で問題ないですが、型によっては問題が起きうることがあるということですね。。
if x is not Noneは対Noneのみだけで判別できているが、if xだとNone以外も含めFalseになり得るということですね。
対Noneを判別したい場合は確かに前者の方が安全な気がしますね。使い方を注意したいと思います。

fast = fast.next.next
if slow == fast:
return True
return False
Copy link

Choose a reason for hiding this comment

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

ちなみにこの解き方はフロイドのアルゴリズムと呼ばれる手品みたいなものだそうです。

setを使った解き方もありますので、ご参考まで

Copy link
Owner Author

Choose a reason for hiding this comment

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

手品という表現は面白いですね・・・知る人ぞ知るトリックって感じのアルゴリズムってことですね。
必ずしも知ってなくてもよいようなアルゴリズムなのですね。。
setを使った解き方もできるのですね!確認してみます。

Copy link

Choose a reason for hiding this comment

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

私の科学手品という表現の意図は、科学に興味を引かせるために使うもの、くらいのつもりです。

たとえば、こういうやつです。偏光で黒い板があるように見えるというもの。
https://www.sci-museum.jp/study/staff/94/

@hroc135
Copy link

hroc135 commented Aug 9, 2024

valを書き換えていく方法は思いつかなかったので勉強になりました。

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