-
Notifications
You must be signed in to change notification settings - Fork 0
Create LinkedListCycleII.md #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?
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,156 @@ | ||
| # step1 何も見ずに解く | ||
|
|
||
| ## 解答 | ||
| - 147. Linked List Cycleそのままなので、何も悩まずかけた。 | ||
| - 計算量 | ||
| - 時間計算量: O(n) | ||
| - 空間計算量: O(n) | ||
| ```java | ||
| /** | ||
| * Definition for singly-linked list. | ||
| * class ListNode { | ||
| * int val; | ||
| * ListNode next; | ||
| * ListNode(int x) { | ||
| * val = x; | ||
| * next = null; | ||
| * } | ||
| * } | ||
| */ | ||
| public class Solution { | ||
| public ListNode detectCycle(ListNode head) { | ||
| if (head == null) { | ||
| return null; | ||
| } | ||
|
|
||
| HashSet<ListNode> visitedNodes = new HashSet<>(); | ||
| ListNode node = head; | ||
|
|
||
| while (node != null) { | ||
| if (visitedNodes.contains(node)) { | ||
| return node; | ||
| } | ||
| visitedNodes.add(node); | ||
| node = node.next; | ||
| } | ||
| return null; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## 解答2 | ||
| - [Rでフロイドの循環検出法を可視化する](https://qiita.com/nozma/items/bfa3e089cd432b74c10d) で始点検出方法を理解し、実装してみる | ||
| - 運用するプログラムの場合、フロイドの循環検出法の概要からコメントを書くが、この場合どこまで書くか | ||
|
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. コメントを書くとしたらフロイドの循環検出法を使っていることも書いておくと親切かなと思います。
Owner
Author
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. たしかにそれくらいは書いておくべきでした。 |
||
| - 計算量 | ||
| - 時間計算量: O(n) | ||
| - 空間計算量: O(1) | ||
| ```java | ||
| public class Solution { | ||
| public ListNode detectCycle(ListNode head) { | ||
| if (head == null) { | ||
| return null; | ||
| } | ||
|
|
||
| // ループを検知 | ||
| ListNode slowNode = head; | ||
| ListNode fastNode = head; | ||
| while (fastNode != null && fastNode.next != null) { | ||
| slowNode = slowNode.next; | ||
| fastNode = fastNode.next.next; | ||
| // 衝突を検知したら中断 | ||
| if (slowNode == fastNode) { | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| if (fastNode == null || fastNode.next == null) { | ||
| return null; | ||
| } | ||
|
|
||
| // ループの始点を探索 | ||
| // fastNodeを先頭に戻し、衝突するまで進める。 | ||
| // 衝突した地点がループの始点 | ||
| fastNode = head; | ||
| while (fastNode != slowNode) { | ||
| slowNode = slowNode.next; | ||
| fastNode = fastNode.next; | ||
| } | ||
| return fastNode; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
|
|
||
| # step2 他の方の解答を見る | ||
|
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. どの方の解答を参考したのかがわかるようにPRのリンクを貼っておくと、参考にした実装からどのあたりを変えた・変えなかったのかがわかってより思考プロセスが浮き彫りになり、議論が盛り上がるかなと思いますので、貼ることをお勧めします。
Owner
Author
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. ありがとうございます! |
||
| Setの解法についてはあまり変更する余地が思いつかなかったので、フロイドの循環検出法で実装 | ||
|
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.
Owner
Author
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. 実装例の紹介ありがとうございます! |
||
| ## 解答 | ||
| - ループ検知部分を関数化してみる。 | ||
| - collisionがパッと思い浮かんだのですがcollisionは違和感あるでしょうか? | ||
|
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. (GPTに聞いた意見ですが)collisionは例外やバグっぽい響きがあるということでGPTにはmeetingを勧められました
Owner
Author
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. やはりcollisionはそういうニュアンスを感じますよね。 |
||
| - step1だと最初に定義した変数を使い回していたが、ループ始点検知のための処理の部分で再定義した方が意味がイメージしやすいなと思い真似してみる | ||
| ```java | ||
| public class Solution { | ||
| public ListNode detectCycle(ListNode head) { | ||
| if (head == null) { | ||
| return null; | ||
| } | ||
|
|
||
| ListNode collisionNode = findCollisionNode(head); | ||
| if (collisionNode == null) { | ||
| return null; | ||
| } | ||
|
|
||
| ListNode fromStart = head; | ||
| ListNode fromCollision = collisionNode; | ||
|
|
||
| while (fromStart == fromCollision) { | ||
|
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. javaに詳しくないので違うかもしれませんが、等しくない限り続けるので!=ではないでしょうか?
Owner
Author
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. おっしゃる通り、!=が正しいです。 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. これは、step2通ったんでしょうか? 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. あー理解しました。Step3で通す前に修正して、passは考えてない感じなんですね。すいません
Owner
Author
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. ご指摘のとおり、正しく動作しません。 |
||
| fromStart = fromStart.next; | ||
| fromCollision = fromCollision.next; | ||
| } | ||
| return fromStart; | ||
| } | ||
|
|
||
| // 衝突したノードを返す、衝突しなければnullを返す | ||
| private ListNode findCollisionNode(ListNode node) { | ||
| ListNode fastNode = node; | ||
| ListNode slowNode = node; | ||
|
|
||
| while (fastNode != null && fastNode.next != null) { | ||
| fastNode = fastNode.next.next; | ||
| slowNode = slowNode.next; | ||
|
|
||
| if (fastNode == slowNode) { | ||
| return fastNode; | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| # step3 3回ミスなく書く | ||
| Set解法で。 | ||
|
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. ちなみに Set 解法で step 3に臨もうと思った理由はなんでしょうか?
Owner
Author
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. Setを用いた実装のほうがシンプルで分かりやすいからです。 |
||
| 141と合わせて何度も書いたのでスラスラ書ける。 | ||
| step1と同様のコード。 | ||
| 所要時間 2分足らず | ||
| ## 解答 | ||
| ```java | ||
| public class Solution { | ||
| public ListNode detectCycle(ListNode head) { | ||
| if (head == null) { | ||
|
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. 一応こちらの条件分岐は無くてもいけますね。nullの場合は確かに例外的な感じがするのであってもよいとも思います。 |
||
| return null; | ||
| } | ||
|
|
||
| HashSet<ListNode> visitedNodes = new HashSet<>(); | ||
| ListNode node = head; | ||
|
|
||
| while (node != null) { | ||
| if (visitedNodes.contains(node)) { | ||
| return node; | ||
| } | ||
| visitedNodes.add(node); | ||
| node = node.next; | ||
| } | ||
| return null; | ||
| } | ||
| } | ||
| ``` | ||
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.
自分なら、HashSet の実装に依存しないコードであれば、
のように、インターフェースで受け取るのですが、好みの問題かもしれません。
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.
確かにHashSet固有のメソッドを使用していないので、HashSetで宣言する意味はあまり無いですね。
一旦、nodchipさんの好みを真似してインターフェース優先で宣言するようにしてみます。