Skip to content

Create ReverseLinkedCycle.md#8

Open
SanakoMeine wants to merge 1 commit intomainfrom
SanakoMeine-patch-5
Open

Create ReverseLinkedCycle.md#8
SanakoMeine wants to merge 1 commit intomainfrom
SanakoMeine-patch-5

Conversation

@SanakoMeine
Copy link
Copy Markdown
Owner


return sentinel.next
```
- 他の人の回答をみてると全部のnextの情報を繋ぐのをやめてメモリを節約するとMemoryLimitに収まるらしいので書いてみる
。printしてみるとリストの各要素がnextの果てまで記録していて、空間計算量がO(N^2)になっていた様で、全く気づいてなかった。
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

これは、二重に間違えています。試しに、

        reversed.next = None
        return sentinel.next

というふうに、return の上に一行足してみましょう。これで動くはずです。

そのうえで、もう一回考察してみて下さい。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

試してみたら動きました。なるほど...。

print(reversed.next)してみたところ"Error - Found cycle in the ListNode"が表示されました。while文の中でずっとループを作りながら遡っていたから、そこにトラップされてエラーを吐いていたのですね。

「2重」と仰っていたのはこれに加えて、意図した動きをしていたら空間計算量は普通にO(N)だからですね。
printされて出てくる

ListNode{val: 5, next: ListNode{val: 4, next: ListNode{val: 3, next: ListNode{val: 2, next: ListNode{val: 1, next: None}}}}}

も今見るとリストの大きさ分保存されているだけですね(今見るとむしろ何を見てO(N^2)と思ったのか不思議です...。Memory Limit Exceededという語感から空間計算量に問題があるという先入観を持ってしまったのだと思います。)。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

理解を一応確認します。最後に pop してきたものの next がその一つ前のやつになっているので、最後の2要素がループになっています。

Memory Limit Exceeded になるのは、おそらく出力を検証している部分が出力をリストに直してから結果を検証しています。そして、そこが無限ループに陥っています。

ここで得られる教訓は、仕事を引き継ぐときに何を引き継いでいるかを意識しようということ、です。

Copy link
Copy Markdown
Owner Author

@SanakoMeine SanakoMeine Jan 8, 2025

Choose a reason for hiding this comment

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

最後に pop してきたものの next がその一つ前のやつになっているので、最後の2要素がループになっています

これは理解できておりました。

出力を検証している部分が出力をリストに直してから結果を検証しています。

具体的な検証の仕方のイメージはついておらず、この推測は立っておりませんでした。

ここで得られる教訓は、仕事を引き継ぐときに何を引き継いでいるかを意識しようということ、です。

ノード1つ分を処理し終えた時にどこまで仕事が終わっているか認識が甘かったために、最後の要素が1つ前の要素を指したままでループを形成してしまったことに気づけなかったものと認識しています。その意味でおっしゃる教訓はキャッチできていると考えています。

scan = scan.next

sentinel = ListNode(0, scan)
reversed = sentinel
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

ありがとうございます、last_nodeやprevious_nodeで考えてみます。

## Step 2
### 学んだこと
- List.reverese()で一発で逆順にしてくれる
- Stackを使う方法、再帰を使う方法(https://github.com/goto-untrapped/Arai60/pull/27/files/14646ec0859dd9411e6983bf6c63e6f15a1f9f32#r1638693522)、
切断して繋ぐ方法、後ろから繋いでいく方法があった。後ろから繋いでいく方法が短くて綺麗。こちらの方が一通りやられている: https://github.com/ichika0615/arai60/pull/6/files
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Memory Limit Exceeded のヒントはこれです。


## Step 3
### コメント
- 切断してから繋ぐやり方の理解が怪しい(過去の問題のPRで指摘され中)のでこれで書いてみる
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

stack.append(scan)
scan = scan.next

sentinel = ListNode(0, scan)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

sentinel.valは使わないので、わざわざ指定せずにsentinel = ListNode(next=scan)でいいんじゃないでしょうか?

https://docs.python.org/3/glossary.html#term-argument

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

そもそも、この scan は必ず None ではないでしょうか。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

最後のnodeで止まっているつもりで書いていた様です...(し、その後stack[-1]をnextにしているしでぐちゃぐちゃですね...)。ありがとうございます。

わざわざ指定せずにsentinel = ListNode(next=scan)でいいんじゃないでしょうか?
今度からはこうしてみます、ありがとうございます。

stack = []

while scan:
stack.append(scan)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

私も最初、よく考えずにノードをスタックにそのまま格納して書いて、MLEでした。
ノードの値の情報だけ抽出してスタックに格納(->その後取り出しながらnewノードを編んでいく流れ)する方法にシフトしたら、解決しました。

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.

4 participants