Skip to content

105. Construct Binary Tree from Preorder and Inorder Traversal#42

Open
skypenguins wants to merge 1 commit into
mainfrom
leetcode/arai60/problem-105
Open

105. Construct Binary Tree from Preorder and Inorder Traversal#42
skypenguins wants to merge 1 commit into
mainfrom
leetcode/arai60/problem-105

Conversation

@skypenguins

Copy link
Copy Markdown
Owner

105. Construct Binary Tree from Preorder and Inorder Traversal

次回予告: 122. Best Time to Buy and Sell Stock II

@skypenguins skypenguins self-assigned this Jul 5, 2026
Comment thread memo.md
```
- preorder は `root < left < right` の順序
- inorder は `left < root < right` の順序

@h-masder h-masder Jul 5, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

言いたいことはわからなくもないですが、定義はしっかりと書いたほうが良いと思います。
特に、今回のアプローチはpreorderとinorderの性質を用いているので、なおさらです。

例えば、以下のサイトのように、定義と例を書いておいてもいいと思います。
https://www.geeksforgeeks.org/dsa/inorder-traversal-of-binary-tree/
https://www.geeksforgeeks.org/dsa/preorder-traversal-of-binary-tree/

Comment thread memo.md

return root

return build_nodes(0, len(preorder) - 1, 0, len(inorder) - 1)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

変数名は略さずに書いたほうが良いかなと思いました。また、midについては、rootのinorder indexという意味のほうが良いと思いました。

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        value_to_inoder_index = {val: i for i, val in enumerate(inorder)}

        def build_nodes(preorder_left, preorder_right, inorder_left, inorder_right):
            if preorder_left > preorder_right:
                return None

            root_value = preorder[preorder_left]
            root = TreeNode(root_value)

            root_inorder_index = value_to_inoder_index[root_value]
            left_subtree_size = root_inorder_index - inorder_left

            root.left = build_nodes(preorder_left + 1, preorder_left + left_subtree_size, inorder_left, root_inorder_index - 1)
            root.right = build_nodes(preorder_left + left_subtree_size + 1, preorder_right, root_inorder_index + 1, inorder_right)

            return root

        return build_nodes(0, len(preorder) - 1, 0, len(inorder) - 1)

@h-masder h-masder Jul 5, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

また、処理は若干複雑だと感じたので、適宜コメントを添えたりしてもいいのかなと思いました。試しに書いてみましたが、全体的に冗長かもしれません。

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        value_to_inorder_index = {value: index for index, value in enumerate(inorder)}

        def build_subtree(preorder_start, preorder_end, inorder_start, inorder_end):
            if preorder_start > preorder_end:
                return None

            # preorder
            # [root][left subtree][right subtree]
            root_value = preorder[preorder_start]
            root = TreeNode(root_value)

            # inorder
            # [left subtree][root][right subtree]
            root_inorder_index = value_to_inorder_index[root_value]
            left_subtree_size = root_inorder_index - inorder_start

            # Update subtree ranges.
            left_subtree_preorder_start = preorder_start + 1
            left_subtree_preorder_end = preorder_start + left_subtree_size
            right_subtree_preorder_start = left_subtree_preorder_end + 1
            right_subtree_preorder_end = preorder_end

            left_subtree_inorder_start = inorder_start
            left_subtree_inorder_end = root_inorder_index - 1
            right_subtree_inorder_start = root_inorder_index + 1
            right_subtree_inorder_end = inorder_end

            root.left = build_subtree(
                left_subtree_preorder_start,
                left_subtree_preorder_end,
                left_subtree_inorder_start,
                left_subtree_inorder_end,
            )

            root.right = build_subtree(
                right_subtree_preorder_start,
                right_subtree_preorder_end,
                right_subtree_inorder_start,
                right_subtree_inorder_end,
            )
            return root

        return build_subtree(0, len(preorder) - 1, 0, len(inorder) - 1)

Comment thread memo.md
stack.append(node.right)

return root
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

関数化したほうが分かりやすいかもしれません。

class Solution:
    def buildTree(self, preorder, inorder):
        if not preorder:
            return None

        root = TreeNode(preorder[0])
        right_subtree_parent_candidates = [root]
        inorder_index = 0

        def find_right_subtree_parent(inorder_index):
            while right_subtree_parent_candidates and right_subtree_parent_candidates[-1].val == inorder[inorder_index]:
                parent_node = right_subtree_parent_candidates.pop()
                inorder_index += 1

            return parent_node, inorder_index

        def attach_left_child(parent_node, child_node):
            parent_node.left = child_node
            right_subtree_parent_candidates.append(child_node)

        def attach_right_child(parent_node, child_node):
            parent_node.right = child_node
            right_subtree_parent_candidates.append(child_node)


        for node_value in preorder[1:]:
            parent_node = right_subtree_parent_candidates[-1]
            child_node = TreeNode(node_value)

            if parent_node.val != inorder[inorder_index]:
                attach_left_child(parent_node, child_node)
            else:
                parent_node, inorder_index = find_right_subtree_parent(inorder_index)
                attach_right_child(parent_node, child_node)

        return root

Comment thread memo.md
return build_nodes(0, len(preorder) - 1, 0, len(inorder) - 1)
```

#### iterative DFS版

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

再帰版とアプローチが異なるようですので、簡単に説明があると読みやすいかと思います。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants