-
Notifications
You must be signed in to change notification settings - Fork 0
617. Merge Two Binary Trees #37
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
Conversation
| Space : O(V) | ||
|
|
||
| 再帰を用いない方法で書いてみる。 | ||
| 参考館演算子は普段なるべく使わないが、使うとnulptr考慮がかなりスッキリかけたので利用する。 |
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.
三項演算子のことですか?「普段なるべく使わない」というのは理由があったりしますか?
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.
三項演算子のことですか?
三項間演算子ですね
三項間演算子は基本的に読みづらくなるので、なるべくif ~ elseを使うようにしています。
今回はそうすると異常に冗長になったので三項間演算子を使用しました。
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.
C++特有の事情があるのかなと思って聞いてみましたが、そういうわけではなかったのですね。ありがとうございます
「間」はいらないと思います
https://ja.wikipedia.org/wiki/%E4%B8%89%E9%A0%85%E6%BC%94%E7%AE%97%E5%AD%90
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.
三項演算子の方が主流な呼び方なんですね
| if (!root1 && !root2) { | ||
| return nullptr; | ||
| } | ||
| stack<pair<vector<TreeNode*>, bool>> next_nodes; |
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.
next_nodesの中身がwhile文の中を読むまでわからなかったので、(C++にそういうものがあれば)構造体を定義したり、コメントをつけたりするといいと思いました。構造体を使わないとしても、vectorを使っていることに違和感がありました。何かしらの方法でleft_node, right_node, merged_nodeの3つが順に入ることを表現した方がいいと思いました。
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.
長さが必ず 3 の vector を使うのは、軽い抵抗があります。意味としては同じものが並んでいるわけではないので。
tuple で4つ並べるのでいいのではないかなと思います。
ただ、これくらいになってくるとそろそろ構造体を定義してもよいかもしれません。
これとだいたい同じですかね。
https://discord.com/channels/1084280443945353267/1245404801177616394/1284010446306803765
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.
ありがとうございます
最後のbool含めてそれぞれ役割が異なるので、構造体でまとめる、tupleでまとめるほうが適切ですね。
| node->right = mergeTrees(root1->right, root2->right); | ||
| return node; | ||
| } | ||
| }; |
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.
このコードだと入力の破壊はしていませんが、入力の木と出力の木でノードが共有されている場合があることに注意しないといけないと思います。例えば下のような場合(pythonコード)にroot1しか書き換えていないつもりがmerged_treeまで書き換わっているということがあります。2_1と2_2のコードだとその点大丈夫そうです
root1 = TreeNode(1)
root2 = None
merged_tree = mergeTrees(root1, root2)
print(merged_tree.val) # 1
root1.val += 1
print(merged_tree.val) # 2There 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.
newする部分木としない部分木があるというのはこの関数を使う側としては怖いので、TreeNode* dupTree(TreeNode* root)などを別途作成して、きちんと全てのnodeをnewするのがよいと思います。
if (!root1) return dupTree(root2);
if (!root2) return dupTree(root1);
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のノードを作って計算を続行するという方法もあるそうです
olsen-blue/Arai60#23 (comment)
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.
C++ だとメモリーリークの関係から一工夫いりますね。
class Solution {
public:
TreeNode* mergeTrees(const TreeNode* root1, const TreeNode* root2) const {
if (!root1 && !root2) {
return nullptr;
}
if (!root1) {
root1 = &dummy;
}
if (!root2) {
root2 = &dummy;
}
TreeNode* node = new TreeNode(root1->val + root2->val);
node->left = mergeTrees(root1->left, root2->left);
node->right = mergeTrees(root1->right, root2->right);
return node;
}
private:
const TreeNode 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.
if (!root1) {
root1 = new TreeNode();
}としてしまうと、tree1で使用されているメモリを解放するときに自分で作成した空のTreeNodeは解放対象にならないということでしょうか?gptに聞いても&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.
newしたオブジェクトはどこかでdelete呼ばないとリークします。
ダミーとして使うroot1は、関数の外でdeleteされないのでこのままだとメモリリークしそうですね。
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はメンバ変数として定義されているのでSolutionクラスのインスタンスがdeleteされるときにdeleteされるということですか?
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.
そうですね、私はその理解です。
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.
理解できました。ありがとうございます
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.
それでよいです。ヒープメモリーの話はどこかにありましたね。
https://discord.com/channels/1084280443945353267/1237649827240742942/1251960606077091981
| return nullptr; | ||
| } | ||
| stack<tuple<TreeNode*, TreeNode*, TreeNode**>> next_nodes; | ||
| auto merged_root = new TreeNode(); |
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.
ここ、nullptr でよいように思います。ループの中で中身が作られていますね。
おおむねいいと思います。
ダブルポインターによる解法はここにもあります。
https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0#heading=h.cxy3cik6kyqx
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.
ありがとうございます。
確かにここの代入は不要でした。
| } | ||
| stack<pair<vector<TreeNode*>, bool>> next_nodes; | ||
| auto merged_root = new TreeNode(); | ||
| if (root1) { |
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, nullptr, nullptr} な番兵を用意して、番兵のアドレスを root1 にセットすれば下の分岐がなくせますかね。
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.
あー、なるほど、番兵を用意すると冗長な三項間演算子が消せますね、ありがとうございます。
https://leetcode.com/problems/merge-two-binary-trees/description/
https://discord.com/channels/1084280443945353267/1183683738635346001/1204277555595845662
hayashi-ay/leetcode#12
shining-ai/leetcode#23
rossy0213/leetcode#12
Mike0121/LeetCode#9
sakupan102/arai60-practice#24
fhiyo/leetcode#25
SuperHotDogCat/coding-interview#35
kazukiii/leetcode#24
TORUS0818/leetcode#25
https://github.com/nittoco/leetcode/pull/30/files
Ryotaro25/leetcode_first60#25
goto-untrapped/Arai60#47
Yoshiki-Iwasa/Arai60#66
seal-azarashi/leetcode#22
hroc135/leetcode#22
tarinaihitori/leetcode#23