-
Notifications
You must be signed in to change notification settings - Fork 0
Create 105. Construct Binary Tree from Preorder and Inorder Traversal.md #12
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
Changes from all commits
d4ccd11
6e981cf
a9406b0
f5c171e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
|
|
||
| ## 再帰による解答 | ||
| --- | ||
| ### 1~3回目 | ||
| 12m25s<br> | ||
| preorder, inorderについて考えていたためか、整理できた。 | ||
| 本番でこの問題を緊張感の中で解けるかはあまり自信がない。 | ||
| 変数が少なく、2~3回目において大きな変更はなし。 | ||
| 時間計算量: O(N)<br> | ||
| 空間計算量: O(N)<br> | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: | ||
| if not preorder or not inorder: | ||
| return None | ||
| root = TreeNode(preorder[0]) | ||
| index_in_inorder = inorder.index(preorder[0]) | ||
| root.left = self.buildTree(preorder[1:index_in_inorder+1], inorder[:index_in_inorder]) | ||
| root.right = self.buildTree(preorder[index_in_inorder+1:], inorder[index_in_inorder+1:]) | ||
|
|
||
| return root | ||
| ``` | ||
|
|
||
| ### stackを利用した解法 | ||
| ```python | ||
| class Solution: | ||
| def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: | ||
| if not preorder or not inorder: | ||
| return None | ||
|
|
||
| root = TreeNode(preorder[0]) | ||
| nodes_with_index = [(root, 0, len(inorder) - 1, 0, len(preorder) - 1)] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. 要素の数が多く、どれが何を表すか分かりにくく感じました。 dataclass や namedtuple などを用いて、各要素に名前 (変数名) を付けてあげたほうが良いと思います。 |
||
| inorder_index_map = {value: index for index, value in enumerate(inorder)} | ||
|
|
||
| while nodes_with_index: | ||
| node, in_start, in_end, pre_start, pre_end = nodes_with_index.pop() | ||
| if pre_start > pre_end or in_start > in_end: | ||
| continue | ||
|
|
||
| root_val = preorder[pre_start] | ||
| mid = inorder_index_map[root_val] | ||
| left_count = mid - in_start | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. right_count を定義しておきます?
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ありがとうございます。確かにそっちの方が読みやすいですね。 |
||
|
|
||
| if left_count > 0: | ||
| left_node = TreeNode(preorder[pre_start + 1]) | ||
| node.left = left_node | ||
| nodes_with_index.append((left_node, in_start, mid - 1, pre_start + 1, pre_start + left_count)) | ||
|
|
||
| if mid < in_end: | ||
| right_node = TreeNode(preorder[pre_start + left_count + 1]) | ||
| node.right = right_node | ||
| nodes_with_index.append((right_node, mid + 1, in_end, pre_start + left_count + 1, pre_end)) | ||
|
|
||
| return root | ||
| ``` | ||
|
|
||
| right_countを定義して利用 | ||
| 変数名: root_val → node_val | ||
| ```python | ||
| class Solution: | ||
| def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: | ||
| if not preorder or not inorder: | ||
| return None | ||
|
|
||
| root = TreeNode(preorder[0]) | ||
| nodes_with_index = [(root, 0, len(inorder) - 1, 0, len(preorder) - 1)] | ||
| inorder_index_map = {value: index for index, value in enumerate(inorder)} | ||
|
|
||
| while nodes_with_index: | ||
| node, in_start, in_end, pre_start, pre_end = nodes_with_index.pop() | ||
| if pre_start > pre_end or in_start > in_end: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 80行目や85行目の判定からこの条件を満たすものしかstackに積んでないことが分かるのでこの条件は不要だと思いました。 |
||
| continue | ||
|
|
||
| node_val = preorder[pre_start] | ||
| mid = inorder_index_map[node_val] | ||
| left_count = mid - in_start | ||
| right_count = in_end - mid | ||
|
|
||
| if left_count > 0: | ||
| left_node = TreeNode(preorder[pre_start + 1]) | ||
| node.left = left_node | ||
| nodes_with_index.append((left_node, in_start, mid - 1, pre_start + 1, pre_start + left_count)) | ||
|
|
||
| if right_count > 0: | ||
| right_node = TreeNode(preorder[pre_start + left_count + 1]) | ||
| node.right = right_node | ||
| nodes_with_index.append((right_node, mid + 1, in_end, pre_start + left_count + 1, pre_end)) | ||
|
|
||
| return root | ||
| ``` | ||
|
|
||
| ## HashMapを用いた解法 | ||
| --- | ||
| ahayashiさん、kandaさんの解答を参考に、HashMapと関数化を利用した解答も書きました。 | ||
| ```python | ||
| class Solution: | ||
| def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: | ||
| def buildtree_helper(left_bound, right_bound): | ||
| nonlocal preorder_index | ||
| if left_bound >= right_bound: | ||
| return | ||
|
|
||
| root_value = preorder[preorder_index] | ||
| root = TreeNode(root_value) | ||
|
|
||
| inorder_index = inorder_value_to_index[root_value] | ||
| preorder_index += 1 | ||
| root.left = buildtree_helper(left_bound, inorder_index) | ||
| root.right = buildtree_helper(inorder_index + 1, right_bound) | ||
| return root | ||
|
|
||
| preorder_index = 0 | ||
| inorder_value_to_index = {} | ||
| for index, value in enumerate(inorder): | ||
| inorder_value_to_index[value] = index | ||
|
Comment on lines
+113
to
+116
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 関数内で使う変数は、関数の定義の前に書いてあった方が個人的には読みやすいです。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ありがとうございます、ご指摘の通りですね。 |
||
|
|
||
| return buildtree_helper(0, len(inorder)) | ||
| ``` | ||
|
|
||
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.
中で
.indexで舐めてるので0(N^2)でしょうか。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.
preorder と inorder のスライスでコピーが作られるので、木が片側に偏っている場合にも O(N2) になると思います。