-
Notifications
You must be signed in to change notification settings - Fork 0
206.reverse linked list #7
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,68 @@ | ||
| 問題:https://leetcode.com/problems/reverse-linked-list/description/ | ||
|
|
||
| ## step1 | ||
|
|
||
| まあ前回に引き続きスタックだからとりあえず全部の->valをpushして走査したら取り出してheadからのリストノードの値を入れ替えてみる。 | ||
| ```cpp | ||
| class Solution { | ||
| public: | ||
| ListNode* reverseList(ListNode* head) { | ||
| stack<int> valstack; | ||
| ListNode* dummy = new ListNode(2147483647,head); | ||
|
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. dummyの役割は何でしょうか?
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. 先頭のポインタを保存しておくために使ったのですが、別に番兵でなくてもよいですね。 |
||
| while (head) { | ||
| valstack.push(head->val); | ||
| head = head->next; | ||
| } | ||
| ListNode *temp = dummy->next; | ||
| while (!valstack.empty()) { | ||
| temp->val = valstack.top(); | ||
|
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. ListNodeの値を書き換えるのは、明示的に言及されていないものの、問題の意図から外れるかもしれません。
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. new演算子に使いなれておらず、無意識にこのような選択をしました。 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. 明示的に書かれていないのですが、ListNodeのnextのみを書き換えるのが、この問題の意図かと思います。
問題に「新しいノード」とは書いていませんね。
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. なるほど、本筋は再帰やループによるnext書き換えであってvalの書き換えと新たなリストの作成は意図からずれるということですね。 |
||
| valstack.pop(); | ||
| temp = temp->next; | ||
| } | ||
| return dummy->next; | ||
|
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. dummyのメモリを解放していないので、メモリリークしています。 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. メモリリークしないようにするにはどうすれば良さそうでしょうか? |
||
| } | ||
| }; | ||
| ``` | ||
| これでaccept。計算量はどちらもO(n)。 | ||
|
|
||
| ## step2 | ||
|
|
||
| 他の方のコード、コメント集を見た。再帰の方法もあるがO(n)。 | ||
| 参考:https://discord.com/channels/1084280443945353267/1231966485610758196/1239417493211320382 | ||
|
|
||
| ```cpp | ||
| class Solution { | ||
| private: | ||
| ListNode* recursion(ListNode* head) { | ||
| if (!head || !head->next) { | ||
| return head; | ||
| } | ||
| else { | ||
| ListNode* newhead = recursion(head->next); | ||
| head->next->next = head; | ||
| head->next = nullptr; | ||
| return newhead; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| 特にこの方の空間計算量O(1)での方法は参考になった。 | ||
| 参考:https://github.com/attractal/leetcode/pull/7/changes#diff-4066faf067589a38d6fd384b7a41db69f3320f5699ad178f6a6df82904e85333R39 | ||
|
|
||
| ```cpp | ||
| class Solution { | ||
| public: | ||
| ListNode* reverseList(ListNode* head) { | ||
| ListNode* previous = nullptr; | ||
| ListNode* node = head; | ||
| while (node != nullptr) { | ||
| ListNode* next_node = node->next; | ||
| node->next = previous; | ||
| previous = node; | ||
| node = next_node; | ||
| } | ||
| return previous; | ||
| } | ||
| }; | ||
| ``` | ||
| 再帰では始めに一番最後のノードが返されるところから最初のノードにまで遡っていくが、この方法ではprevious=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.
ここで「イニシャルコスト」はどういう意味で使っていますか?
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. ループの中にnullptrを繋げる処理を書かずにループの外側で最初のノードにのみnullptrを繋げる処理を行うという意味で使っています。 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.
これはコードと振る舞いが違いませんか?単にpreviousをnullptrで初期化しているように見えます。
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. 再帰で書いたときに毎回nullptrを代入していたことと比較しての説明です。 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. 意図は理解しましたが、単にpreviousをnullptrで初期化することを「キレイじゃない」と言うことに違和感があります。イニシャルコストという表現も、重い処理が最初に走るようなイメージがあります。 |
||
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.
どうして値を2147483647にしましたか?
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.
コメントありがとうございます。
int型のmax valueを番兵に用いています。
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.
どうして0や他の値ではなく、INT_MAXを値として選びましたか?
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.
dummyノードの値は一度も使用していないので、番兵(コードを簡略化するための値)としての役割はなさそうです。
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.
ご返信ありがとうございます。
その通りです。この場合headを保存しておけばよいだけですね。
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.
わざわざ2147483647と書いて、(環境依存になる)intの最大値を選んだ理由はありますか?仮にINT_MAXが必要だったとしても、リテラルで書くのは好ましくないように思います。