-
Notifications
You must be signed in to change notification settings - Fork 0
141. Linked List Cycle #12
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
## Problem | ||
https://leetcode.com/problems/linked-list-cycle/ | ||
|
||
## Step 1 | ||
5分程度答えを見ずに考えて、手が止まるまでやってみる。 | ||
何も思いつかなければ、答えを見て解く。ただし、コードを書くときは答えを見ないこと。 | ||
動かないコードも記録する。 | ||
正解したら一旦OK。思考過程もメモする。 | ||
|
||
### Approach | ||
* 素直に手でやるならどうかと考えたやり方 | ||
* ListNodeを1つずつ走査しながらHashSetに訪問済のListNodeを順次格納していき、新たに訪問したListNodeがSetの中にあったらtrue | ||
* 空間計算量がO(n)と高いので、もっといい方法ありそうと思いながら書いた | ||
|
||
```java | ||
public class Solution { | ||
public boolean hasCycle(ListNode head) { | ||
ListNode current = head; | ||
HashSet<ListNode> visitedSet = new HashSet<>(); | ||
|
||
while (current != null) { | ||
if (visitedSet.contains(current)) { | ||
return true; | ||
} | ||
visitedSet.add(current); | ||
current = current.next; | ||
} | ||
return false; | ||
} | ||
} | ||
``` | ||
|
||
## Step 2 | ||
他の方が描いたコードを見て、参考にしてコードを書き直してみる。 | ||
参考にしたコードのリンクは貼っておく。 | ||
読みやすいことを意識する。 | ||
他の解法も考えみる。 | ||
|
||
### 他の方のPR | ||
* https://github.com/onyx0831/leetcode/pull/1 | ||
* https://github.com/t0hsumi/leetcode/pull/1 | ||
* https://github.com/ryuryu5121/Arai60/pull/1 | ||
* https://github.com/hajimeito1108/arai60/pull/1 | ||
* https://github.com/lilnoahhh/leetcode/pull/1 | ||
|
||
|
||
### 解法1. フロイドの循環検出法 | ||
* 1つ飛ばしで進むウサギ(fast)と1つずつ進む亀(slow)の2つのポインタを同時に同じリスト上を走らせると、サイクルがある場合必ずどこかのノードで合流するという考え方 | ||
* https://en.wikipedia.org/wiki/Cycle_detection#Floyd's_tortoise_and_hare | ||
* 感想: 2つ走らせるという発想はなかった。時間をかけても自分でゼロから思いつくのは厳しいと思う。考え方のパターンとしてストックしたい | ||
* [追記]レビュアーからのコメントとして、この解法は科学手品のようなものなので自分で思いつけなくてもあまり気にしなくてよいとのこと。一方でStep1のSetを使った解法は思いつけて普通とのこと | ||
|
||
```java | ||
public class Solution { | ||
public boolean hasCycle(ListNode head) { | ||
ListNode fast = head | ||
ListNode slow = head; | ||
|
||
while (fast != null && fast.next != null) { // Check the lead runner fast. | ||
fast = fast.next.next; | ||
slow = slow.next; | ||
if (fast == slow) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
} | ||
``` | ||
### 解法2. 訪問済NodeをSetに格納する方法 | ||
* Step1 と同じものだが、current という命名がわかりづらいという事がたびたび議論になっているため、nodeに変更 | ||
* https://github.com/katsukii/leetcode/pull/12#discussion_r1932786013 | ||
* また、変数名に型名を入れるのはよくないため、 visitedSet -> visitedNodes に変更 | ||
|
||
```java | ||
public class Solution { | ||
public boolean hasCycle(ListNode head) { | ||
ListNode node = head; | ||
HashSet<ListNode> visitedNodes = new HashSet<>(); | ||
Comment on lines
+75
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. レビュー遅くなりすみません。 全体的に良いと思います!ただすでに指摘されているように変数名が気になりました。visitedNodesのように変数名に大文字を含むのはpepでは推奨されていないようです。
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. おそらく別のドキュメントですが、仰る通り同じく、PEP8 という規約では変数名と関数名は lower_case_with_underscores を使いましょうとなっているようです。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @lilnoahhh @olsen-blue 変数名の命名規則に関してですが、PEP8はPython向けの規約のため一概にJavaのコードに適用すべきではないと考えています。以下はGoogleのコーディング規約ですが、JavaではlowerCamelCaseが推奨されているようです。
https://google.github.io/styleguide/javaguide.html#s5.2.7-local-variable-names There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. その通りですね、失礼しました |
||
|
||
while (node != null) { | ||
if (visitedNodes.contains(node)) { | ||
return true; | ||
} | ||
visitedNodes.add(node); | ||
node = current.next; | ||
} | ||
return false; | ||
} | ||
} | ||
``` | ||
|
||
## Step 3 | ||
今度は、時間を測りながら、もう一回書く。 | ||
アクセプトされたら消すを3回連続できたら問題はOK。 | ||
|
||
```java | ||
public class Solution { | ||
public boolean hasCycle(ListNode head) { | ||
ListNode fast = head | ||
ListNode slow = head; | ||
|
||
while (fast != null && fast.next != null) { // Check the lead runner fast. | ||
fast = fast.next.next; | ||
slow = slow.next; | ||
if (fast == slow) { | ||
return true; | ||
} | ||
} | ||
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.
全体的に良いと思います。Discord内に直感的な解説も転がってるので、まだ見てなければどうぞ。
https://discord.com/channels/1084280443945353267/1246383603122966570/1252209488815984710
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.
非常に分かりやすいですね。とても参考になりました。
ありがとうございます。