-
Notifications
You must be signed in to change notification settings - Fork 0
Create 617. Merge Two Binary Trees #31
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,87 @@ | ||
| # [617. Merge Two Binary Trees](https://leetcode.com/problems/merge-two-binary-trees/description/) | ||
| ## Step1 | ||
| /*答えを見て理解できたと思ったら、答えを隠して書いて下さい。筆が進まず、5分迷ったら答えを見て下さい。そして、見ちゃったら一回全部消してやり直しです。答えを送信して、正解になったら、まず1段落目です。*/ | ||
| ### 問題意図の考察 | ||
| - 問題文の確認 | ||
| - 二分木:roo1, roo2が与えられる。 | ||
| - root1とroot2をマージして下さい、 | ||
| - ルールがある | ||
| - 2つのノードが重なる場合、その値を合計し新しいノードの値する | ||
| - どちらか一方がnullの場合、新しい木のノードとして採用する | ||
|
|
||
| - 制約の確認 | ||
| - The number of nodes in both trees is in the range [0, 2000]. | ||
| - ノードの数は最大:2000 | ||
| - O(N), O(n log n)がベター、O(n^2)だと効率という点では微妙かな | ||
| - -10^4 <= Node.val <= 10^4 | ||
| - ノードの値:-10,000~10,000 | ||
| - 足しても +- 2 * 10^4 | ||
|
|
||
| - 問題意図 | ||
| - 根から走査して、順番にマージできるか | ||
|
|
||
| ### 解法を考える。 | ||
| - 再帰の書き方が自然な流れのように感じる | ||
| - null の扱いができるか | ||
| - root1->nullの時、root2を返す | ||
| - root2->nullの時、root1を返す | ||
| - root1->val += root2->val | ||
| - root1の二分木にまとめる感覚 | ||
|
|
||
| 初回の回答 | ||
| ```cpp | ||
| class Solution { | ||
| public: | ||
| TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) { | ||
| if (root1 == nullptr) { | ||
| return root2; | ||
| } | ||
| if (root2 == nullptr) { | ||
| return root1; | ||
| } | ||
|
|
||
| root1->val += root2->val; | ||
|
|
||
| root1->left = mergeTrees(root1->left, root2->left); | ||
| root1->right = mergeTrees(root1->right, root2->right); | ||
|
|
||
| return root1; | ||
| } | ||
| }; | ||
|
|
||
| ``` | ||
|
|
||
| ## 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. step2とStep3のコードが無い気がします。アップいただけますでしょうか。
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.
|
||
| /*次にコードを読みやすくなるようにできるだけ整えましょう。これで動くコードになったら完成です。*/ | ||
| - 改善点 | ||
| - root1に足していくというのがシンプルだと思ったが、結構違うやり方をしている人が多い。 | ||
| - 最近シンプルに書けることによってしまってるかも知れない。選択肢を増やして正しい判断ができるようにしたい。 | ||
|
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. 進め方は人それぞれなのでお任せしたいですが、全体的に拝見し、個人的にはもう少し選択肢とそれらのトレードオフについて広く検討されても良いかもしれないなと感じました。例えばですが: 再帰
https://discord.com/channels/1084280443945353267/1350090869390311494/1354492544049877134
https://discord.com/channels/1084280443945353267/1350090869390311494/1355224179720458261
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. @docto-rin 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. @oda |
||
| - 今回の問題に関してはstep1が自然に感じるのでそのままstep3へ | ||
|
|
||
| - 他の方のコードを読む | ||
| - https://github.com/5103246/LeetCode_Arai60/pull/22/commits/f2ddfbc88c74bb14d0f640f9b2a0d9f9f110003d | ||
| - https://github.com/nktr-cp/leetcode/pull/24/commits/1b6c1d4db51b3a4e22797b82da4be99b91b8e130#diff-d16010dc25fbb50a03680c436bbb0d90f462bf27b3aa26421f1df94d5f15aa15 | ||
| - 新しい二分木:new TreeNode()を作成する。root1/root2を壊さずに作成 | ||
| - node1, node2, merged_nodeと3つの組み合わせをキューに入れる | ||
| - 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. リンク先のコメントが参考になりました。C++の経験がないといつもの癖でnewとしそうなので、今後C++を書く際に気をつけられそうです。 |
||
| - メモリ | ||
| - 動的メモリ:https://en.cppreference.com/w/cpp/language/new.html | ||
| - https://en.cppreference.com/w/cpp/memory.html | ||
| - Effective C++ 確認 | ||
|
|
||
| - 他の解法 | ||
| - python | ||
| - https://github.com/tshimosake/arai60/pull/14/commits/253f33c504c73c4709dafa575c47a9a0f3f0b5ab | ||
| - | ||
| - C++ | ||
| - https://github.com/irohafternoon/LeetCode/pull/26/commits/d67d4b4a3959fb02d773249be55806988155817b | ||
| - https://github.com/Ryotaro25/leetcode_first60/pull/25/commits/b67018715bbcb6efaa049d09590460cbb23774b1#diff-1296319066657d7ffa73cc35ea8dab0b8bb061399fa3382e925bf62f940038e3 | ||
|
Comment on lines
+73
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. URLだけでなく読んだ感想をペアにして列挙していただくとレビュワーの助けになると思います。 例:Step Xの実装が良い、読みやすい、シンプルだと思った。ここの部分は自分ならこう書きたい。ここの部分で複数の選択肢を検討していて良いと思った。など |
||
|
|
||
|
|
||
| ## Step3 | ||
| /*そしたら、また全部消しましょう。今度は時間を測りながら、もう一回、書きましょう。書いてアクセプトされたら文字を消して再度書きましょう。これを10分以内に一回もエラーを出さずに書ける状態になるまで続けて下さい。3回続けてそれができたらその問題はひとまず丸です。*/ | ||
| 1. 8min | ||
| 2. 7min | ||
| 3. 7min | ||
|
|
||
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.
ここを読んで少なくとも自分の感覚とはズレていると感じました。
自分はこの問題を見たとき、rootからトップダウンに作業してO(n)で行けるのはほぼ自明で、速度の議論については定数倍でしか起きないと感じました。
それよりも重要なのは、Step 1で書かれたコードはほぼ最速ですが、入力を破壊している点が気になります。返り値のある関数で入力が破壊される場合、呼び出した人はびっくりすると思います。
実務ならAPIドキュメントに仕様として明記しておいたり、入力を破壊するかどうか引数で選択できるなどの配慮が必要だと思います。
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.
@docto-rin
ご指摘ありがとうございます。
root1 を上書きする破壊的なマージになっている点認識しました。LeetCode上では問題ないように見えますが、実務的なAPIであれば「入力を破壊すること」をドキュメントで明示するか、非破壊的を用意するのが望ましいという点大変勉強になりました。
また実務経験はないのですが、この点他の方のコードを読んだ時に気づけたはずだったのでどんな違いがあるのか注意深く意識してみます。