From b1546f22ee67e452cd032388f3f33572455d583c Mon Sep 17 00:00:00 2001 From: SuperHotDogCat Date: Sat, 15 Feb 2025 21:10:04 +0900 Subject: [PATCH 1/3] solved construct_binary_tree_from_preorder_and_inorder_traversal --- .../phase1.py | 26 +++++++++ .../phase2.py | 56 +++++++++++++++++++ .../phase3.py | 17 ++++++ 3 files changed, 99 insertions(+) create mode 100644 construct_binary_tree_from_preorder_and_inorder_traversal/phase1.py create mode 100644 construct_binary_tree_from_preorder_and_inorder_traversal/phase2.py create mode 100644 construct_binary_tree_from_preorder_and_inorder_traversal/phase3.py diff --git a/construct_binary_tree_from_preorder_and_inorder_traversal/phase1.py b/construct_binary_tree_from_preorder_and_inorder_traversal/phase1.py new file mode 100644 index 0000000..5897ed6 --- /dev/null +++ b/construct_binary_tree_from_preorder_and_inorder_traversal/phase1.py @@ -0,0 +1,26 @@ +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right + +# preorder, inorderを受け取るとその部分木を生成する関数を組むように制作した + +class Solution: + def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: + if len(preorder) == 0: + return None + + node = TreeNode() + root_id = preorder[0] + index = inorder.index(root_id) + node.val = root_id + left_inorder = inorder[:index] + left_preorder = preorder[1:1+len(left_inorder)] + right_inorder = inorder[index + 1:] + right_preorder = preorder[1+len(left_inorder):] + node.left = self.buildTree(left_preorder, left_inorder) + node.right = self.buildTree(right_preorder, right_inorder) + + return node diff --git a/construct_binary_tree_from_preorder_and_inorder_traversal/phase2.py b/construct_binary_tree_from_preorder_and_inorder_traversal/phase2.py new file mode 100644 index 0000000..0453851 --- /dev/null +++ b/construct_binary_tree_from_preorder_and_inorder_traversal/phase2.py @@ -0,0 +1,56 @@ +# olsen-blue: https://github.com/olsen-blue/Arai60/pull/29/files + # preorderの呼び出され方を考えると副作用のある関数を許せば関数が呼び出されるたびにpreorderのindexを1つ進めるだけでよくなる, スライス操作の方は確かにphase1でも書いたが個人的にも速度とかの低下が怖い +# hroc135: https://github.com/hroc135/leetcode/pull/28/files +# kazukiii: https://github.com/kazukiii/leetcode/pull/30/files +# seal-azarashi: https://github.com/seal-azarashi/leetcode/pull/29#discussion_r1813998042 +# nittoco: https://github.com/nittoco/leetcode/pull/37/files + +# 副作用のあるhelper関数を許す +class Solution: + def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: + preorder_index = -1 + def build_tree_helper(left: int, right: int) -> Optional[TreeNode]: + if left > right: + return None + nonlocal preorder_index + preorder_index += 1 + node = TreeNode(preorder[preorder_index]) + inorder_split_index = inorder.index(preorder[preorder_index]) # ここの行をmapにすると速くはなる + node.left = build_tree_helper(left, inorder_split_index - 1) + node.right = build_tree_helper(inorder_split_index + 1, right) + return node + + return build_tree_helper(0, len(preorder) - 1) + +# 範囲情報を入れてpreorder順に見ていく場合の実装(参考: https://github.com/nittoco/leetcode/pull/37/files) +from dataclasses import dataclass + +@dataclass +class InorderPosition: + node: TreeNode + left_limit: int + right_limit: int + +class Solution: + def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: + dummy = TreeNode() + stack = [InorderPosition(dummy, inf, inf)] + node_val_to_inorder_index = {val: i for i, val in enumerate(inorder)} + for node_id in preorder: + inorder_split_index = node_val_to_inorder_index[node_id] + node = TreeNode(node_id) + back = stack[-1] + if inorder_split_index < back.left_limit: + back.node.left = node + stack.append(InorderPosition(node, inorder_split_index, back.left_limit)) + continue + back = self.search_parent_of_right_child(inorder_split_index, stack) + back.node.right = node + stack.append(InorderPosition(node, inorder_split_index, back.right_limit)) + return dummy.left + + def search_parent_of_right_child(self, inorder_split_index: int, stack: list[InorderPosition]) -> InorderPosition: + while stack: + if inorder_split_index < stack[-1].right_limit: + return stack[-1] + stack.pop() diff --git a/construct_binary_tree_from_preorder_and_inorder_traversal/phase3.py b/construct_binary_tree_from_preorder_and_inorder_traversal/phase3.py new file mode 100644 index 0000000..a588e93 --- /dev/null +++ b/construct_binary_tree_from_preorder_and_inorder_traversal/phase3.py @@ -0,0 +1,17 @@ +# 副作用はあるが, sliceとかコピーをなしにして自分がギリギリ思いつきそうな解答を書いた + +class Solution: + def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: + preorder_index = -1 + node_val_to_inorder_index = {val: i for i, val in enumerate(inorder)} + def build_tree_helper(left: int, right: int): + if left > right: + return + nonlocal preorder_index + preorder_index += 1 + split_index = node_val_to_inorder_index[preorder[preorder_index]] + node = TreeNode(preorder[preorder_index]) + node.left = build_tree_helper(left, split_index - 1) + node.right = build_tree_helper(split_index + 1, right) + return node + return build_tree_helper(0, len(inorder) - 1) From bde201b1a664dfcd620d9b56cab2eea1e6c639c1 Mon Sep 17 00:00:00 2001 From: SuperHotDog <115141367+SuperHotDogCat@users.noreply.github.com> Date: Sat, 15 Feb 2025 21:16:29 +0900 Subject: [PATCH 2/3] =?UTF-8?q?phase1.py=E3=81=AB=E3=82=B9=E3=83=9A?= =?UTF-8?q?=E3=83=BC=E3=82=B9=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../phase1.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/construct_binary_tree_from_preorder_and_inorder_traversal/phase1.py b/construct_binary_tree_from_preorder_and_inorder_traversal/phase1.py index 5897ed6..0b62e0c 100644 --- a/construct_binary_tree_from_preorder_and_inorder_traversal/phase1.py +++ b/construct_binary_tree_from_preorder_and_inorder_traversal/phase1.py @@ -17,9 +17,9 @@ def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNod index = inorder.index(root_id) node.val = root_id left_inorder = inorder[:index] - left_preorder = preorder[1:1+len(left_inorder)] + left_preorder = preorder[1:1 + len(left_inorder)] right_inorder = inorder[index + 1:] - right_preorder = preorder[1+len(left_inorder):] + right_preorder = preorder[1 + len(left_inorder):] node.left = self.buildTree(left_preorder, left_inorder) node.right = self.buildTree(right_preorder, right_inorder) From e5648732a8d106cced4b40f44e3b946701edc490 Mon Sep 17 00:00:00 2001 From: SuperHotDog <115141367+SuperHotDogCat@users.noreply.github.com> Date: Fri, 28 Feb 2025 22:43:57 +0900 Subject: [PATCH 3/3] =?UTF-8?q?construct=5Fbinary=5Ftree=5Ffrom=5Fpreorder?= =?UTF-8?q?=5Fand=5Finorder=5Ftraversal=E3=82=922=E9=80=9A=E3=82=8A?= =?UTF-8?q?=E3=81=AE=E3=82=84=E3=82=8A=E6=96=B9=E3=81=A7=E7=9B=B4=E3=81=97?= =?UTF-8?q?=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../phase4.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 construct_binary_tree_from_preorder_and_inorder_traversal/phase4.py diff --git a/construct_binary_tree_from_preorder_and_inorder_traversal/phase4.py b/construct_binary_tree_from_preorder_and_inorder_traversal/phase4.py new file mode 100644 index 0000000..8f60340 --- /dev/null +++ b/construct_binary_tree_from_preorder_and_inorder_traversal/phase4.py @@ -0,0 +1,33 @@ +# https://github.com/SuperHotDogCat/coding-interview/pull/43#discussion_r1958958113 +# このコードを買いている時どうも命名に気を配れていなかった。数字でノード1つを指定できるのでidという名前にしていたがTreeNodeの名前はvalなのでそこが違うために困惑させたコードになってしまっていた +# あとは変数を定義してから使うまでを離さないように + +class Solution: + def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: + if len(preorder) == 0: + return None + + root_val = preorder[0] + root = TreeNode(root_val) + root_inorder_index = inorder.index(root_val) + root.left = self.buildTree(preorder[1:1 + root_inorder_index], inorder[:root_inorder_index]) + root.right = self.buildTree(preorder[1 + root_inorder_index:], inorder[root_inorder_index + 1:]) + return root + +# https://github.com/SuperHotDogCat/coding-interview/pull/43/files#r1958006329 +# https://github.com/SuperHotDogCat/coding-interview/pull/43/files#r1957333097 コメント: 個人的にはどれくらい消費したかを返り値で返して欲しいですね<-消費したかを返す実装で自分は沼にハマってしまったのでpreorder_indexを返すように関数を変更して副作用を消すようにした +class Solution: + def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: + node_val_to_inorder_index = {val: i for i, val in enumerate(inorder)} + + def build_tree_helper(left: int, right: int, preorder_index: int): + # preorder_indexは常に次探索すべきpreorderのindexを指すように制作 + if left > right: + return None, preorder_index + node = TreeNode(preorder[preorder_index]) + split_index = node_val_to_inorder_index[preorder[preorder_index]] + preorder_index += 1 + node.left, preorder_index = build_tree_helper(left, split_index - 1, preorder_index) + node.right, preorder_index = build_tree_helper(split_index + 1, right, preorder_index) + return node, preorder_index + return build_tree_helper(0, len(inorder) - 1, 0)[0]