Skip to content

Conversation

@kazukiii
Copy link
Owner

問題へのリンク
https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/description/

次に解く問題
276. Paint Fence

README.mdへ頭の中の言語化と記録をしています。

Copy link

@hayashi-ay hayashi-ay left a comment

Choose a reason for hiding this comment

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

良いと思います。

Choose a reason for hiding this comment

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

初めてみるタイプの解き方で面白かったです。毎回rootから探索しているのは気になりますね。

Copy link

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 に入れないといけないように思います。

Copy link

Choose a reason for hiding this comment

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

inorder での頭から構築することもできますかね。

少なくとも right が空いているやつだけが追加先の候補になって、かつ、追加する先ではないという判定が出るとそこに付くことはないですよね。だから、スタックを用意し、まだ、right が空いているノードをスタックに積んでおいてスタックの上からつける先であるかを判定していき、つける先ではなければスタックから取り除き、付ける場所が見つかったらスタックに積めばいけるんじゃないでしょうか。全体の根本になる場合があるのがちょっと複雑かしら。

Copy link
Owner Author

Choose a reason for hiding this comment

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

アイデアありがとうございます。明日実装してみようと思います。

Copy link
Owner Author

Choose a reason for hiding this comment

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

こちらにQueueを使ったpreorderを頭から見ていく実装を追加しました。ea6c089

Copy link

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;
    }
};

Copy link

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;
    }
};

Copy link

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];

Choose a reason for hiding this comment

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

atかfindにしたら、const &でマップを渡せますね。

Copy link
Owner Author

Choose a reason for hiding this comment

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

コンパイルエラーになったためconstを外した経緯があったんですが、atかfindにすれば良いんですね。ありがとうございます。

Copy link

@fhiyo fhiyo left a comment

Choose a reason for hiding this comment

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

良いと思います!

Comment on lines +27 to +30
int inorder_root_index = inorder_start;
while (inorder[inorder_root_index] != root_value) {
inorder_root_index++;
}
Copy link

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();

Copy link
Owner Author

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;
Copy link

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)

Copy link
Owner Author

Choose a reason for hiding this comment

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

ありがとうございます、参考になりました。
chroniumのガイドラインに従うとこのケースの場合はmapで十分と理解しました。

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.

7 participants