105. Construct Binary Tree from Preorder and Inorder Traversal#42
105. Construct Binary Tree from Preorder and Inorder Traversal#42skypenguins wants to merge 1 commit into
Conversation
| ``` | ||
| - preorder は `root < left < right` の順序 | ||
| - inorder は `left < root < right` の順序 | ||
|
|
There was a problem hiding this comment.
言いたいことはわからなくもないですが、定義はしっかりと書いたほうが良いと思います。
特に、今回のアプローチはpreorderとinorderの性質を用いているので、なおさらです。
例えば、以下のサイトのように、定義と例を書いておいてもいいと思います。
https://www.geeksforgeeks.org/dsa/inorder-traversal-of-binary-tree/
https://www.geeksforgeeks.org/dsa/preorder-traversal-of-binary-tree/
There was a problem hiding this comment.
参考サイトの提示ありがとうございます。確かにこの表現だと曖昧さがありました。
|
|
||
| return root | ||
|
|
||
| return build_nodes(0, len(preorder) - 1, 0, len(inorder) - 1) |
There was a problem hiding this comment.
変数名は略さずに書いたほうが良いかなと思いました。また、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)There was a problem hiding this comment.
また、処理は若干複雑だと感じたので、適宜コメントを添えたりしてもいいのかなと思いました。試しに書いてみましたが、全体的に冗長かもしれません。
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)There was a problem hiding this comment.
コードの改善案をありがとうございます。コメントと一時変数を導入すると少し冗長に感じますね。
| stack.append(node.right) | ||
|
|
||
| return root | ||
| ``` |
There was a problem hiding this comment.
関数化したほうが分かりやすいかもしれません。
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| return build_nodes(0, len(preorder) - 1, 0, len(inorder) - 1) | ||
| ``` | ||
|
|
||
| #### iterative DFS版 |
There was a problem hiding this comment.
再帰版とアプローチが異なるようですので、簡単に説明があると読みやすいかと思います。
105. Construct Binary Tree from Preorder and Inorder Traversal
次回予告: 122. Best Time to Buy and Sell Stock II