-
Notifications
You must be signed in to change notification settings - Fork 0
105. Construct Binary Tree from Preorder and Inorder Traversal #30
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?
105. Construct Binary Tree from Preorder and Inorder Traversal #30
Conversation
hayashi-ay
left a 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.
良いと思います。
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から探索しているのは気になりますね。
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 から探索していますけれども、Queue を用意して root を入れて、木の構築をしながら Queue に足していくと、次に足す node のつける先は Queue から出てきますね。ただ、left か right か見逃すかの情報が先祖の inorder_value_to_index から決まるので、先祖の範囲も Queue に入れないといけないように思います。
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.
inorder での頭から構築することもできますかね。
少なくとも right が空いているやつだけが追加先の候補になって、かつ、追加する先ではないという判定が出るとそこに付くことはないですよね。だから、スタックを用意し、まだ、right が空いているノードをスタックに積んでおいてスタックの上からつける先であるかを判定していき、つける先ではなければスタックから取り除き、付ける場所が見つかったらスタックに積めばいけるんじゃないでしょうか。全体の根本になる場合があるのがちょっと複雑かしら。
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.
こちらにQueueを使ったpreorderを頭から見ていく実装を追加しました。ea6c089
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.
これ、なんか見返していたのですが、私のコメント、なんだかとても混乱しているように思いました。
1つ目のコメントはおそらく、Queue ではなくて Stack のはずですね。
想定していたのは、下のような実装です。
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
map<int, int> inorder_value_to_index;
for (int i = 0; i < inorder.size(); i++) {
inorder_value_to_index[inorder[i]] = i;
}
TreeNode dummy(numeric_limits<int>::max());
inorder_value_to_index[numeric_limits<int>::max()] = numeric_limits<int>::max();
vector<pair<TreeNode*, int>> stack;
stack.emplace_back(&dummy, numeric_limits<int>::max());
for (int p: preorder) {
TreeNode* node = new TreeNode(p);
int node_position = inorder_value_to_index[node->val];
while (1) {
auto [parent, grand_parent_position] = stack.back();
int parent_position = inorder_value_to_index[parent->val];
if (node_position < parent_position) {
parent->left = node;
stack.emplace_back(node, parent_position);
break;
}
if (node_position < grand_parent_position) {
parent->right = node;
stack.pop_back();
stack.emplace_back(node, grand_parent_position);
break;
}
stack.pop_back();
}
}
return dummy.left;
}
};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.
少し整理してみました。
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
map<int, int> inorder_position;
for (int i = 0; i < inorder.size(); i++) {
inorder_position[inorder[i]] = i;
}
TreeNode dummy;
// contains all nodes that may have a child.
// The second and the third values represent the maximum value of its left and right children respectively.
vector<tuple<TreeNode*, int, int>> stack;
stack.emplace_back(&dummy, numeric_limits<int>::max(), numeric_limits<int>::max());
for (int p: preorder) {
TreeNode* node = new TreeNode(p);
int node_position = inorder_position[node->val];
auto [parent, left_limit, right_limit] = stack.back();
if (node_position < left_limit) {
parent->left = node;
stack.emplace_back(node, node_position, left_limit);
continue;
}
while (1) {
auto [parent, left_limit, right_limit] = stack.back();
if (node_position < right_limit) {
parent->right = node;
stack.pop_back();
stack.emplace_back(node, node_position, right_limit);
break;
}
stack.pop_back();
}
}
return dummy.left;
}
};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.
inorder での頭から構築はこんなのです。これはかなりお気に入り。
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
map<int, int> preorder_position;
for (int i = 0; i < preorder.size(); i++) {
preorder_position[preorder[i]] = i;
}
// contains all nodes whose .right hasn't been decided yet.
vector<TreeNode*> stack;
auto gather_descendants = [&](int node_position) {
TreeNode* child = nullptr;
while (!stack.empty()) {
TreeNode* back = stack.back();
if (preorder_position[back->val] < node_position) {
break;
}
stack.pop_back();
back->right = child;
child = back;
}
return child;
};
for (int i: inorder) {
TreeNode* node = new TreeNode(i);
int node_position = preorder_position[node->val];
node->left = gather_descendants(node_position);
stack.emplace_back(node);
}
return gather_descendants(numeric_limits<int>::min());
}
};| unordered_map<int, int>& inorder_value_to_index) { | ||
| if (subtree_size == 0) return nullptr; | ||
| int root_value = preorder[preorder_start]; | ||
| int inorder_root_index = inorder_value_to_index[root_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.
atかfindにしたら、const &でマップを渡せますね。
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.
コンパイルエラーになったためconstを外した経緯があったんですが、atかfindにすれば良いんですね。ありがとうございます。
fhiyo
left a 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.
良いと思います!
| int inorder_root_index = inorder_start; | ||
| while (inorder[inorder_root_index] != root_value) { | ||
| inorder_root_index++; | ||
| } |
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 inorder_root_index = find(
inorder.begin() + inorder_start,
inorder.begin() + inorder_end,
root_value
) - inorder.begin();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* buildTree(vector<int>& preorder, vector<int>& inorder) { | ||
| unordered_map<int, int> inorder_value_to_index; |
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.
unordered_map を使うか map を使うかについて、こちらが参考になると思います。
Ryotaro25/leetcode_first60#22 (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.
ありがとうございます、参考になりました。
chroniumのガイドラインに従うとこのケースの場合はmapで十分と理解しました。
問題へのリンク
https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/description/
次に解く問題
276. Paint Fence
README.mdへ頭の中の言語化と記録をしています。