diff --git a/arai60/merge-two-binary-trees/README.md b/arai60/merge-two-binary-trees/README.md new file mode 100644 index 0000000..818284f --- /dev/null +++ b/arai60/merge-two-binary-trees/README.md @@ -0,0 +1,36 @@ +## 考察 +- 初見の問題 +- 方針 + - DFS/BFS + - 全ノードを探索しながら新しい二分木を生成して返すのが思い付く + - どちらかの二分木を再利用もできそうだが、新しい二分木を作る方を選択 + - Pythonで関数からの戻り値をいじったら、他のところが壊れましたはびっくりしそう +- 再帰の最大深さが2000だが、まずは再帰で書いてみる +- Step2で非再帰に書き直そうと思う +- あとは実装 + +## Step1 +- 再帰DFSで実装 +- time: O(n), space: O(n) + +## Step2 +- 非再帰に書き換え + - 3点を書き換えた + - popの位置に再帰関数の処理を持ってくる + - 再帰呼び出しをstackへのappendに変更 + - returnをcontinueへ変更 + - stack -> queueとすればBFSにもなる +- 他の人のPRを検索 + - めちゃくちゃシンプル + - https://github.com/SuperHotDogCat/coding-interview/pull/35/files#diff-e23bfd258f7b29f3e94954b1beeca569cce5d7f3b17de6f3223729c1ebf588a5 + - 帰りがけで下から構築していくのは思い付かなかった... + - これならhelperも作る必要ない + - こちらもめちゃくちゃシンプル + - https://github.com/fhiyo/leetcode/pull/25 + - 行きがけで書くにしてももう少し条件を整理できそう +- 帰りがけDFSで実装してみる + +## Step3 +- 1回目: 1m36s +- 2回目: 1m15s +- 3回目: 1m17s diff --git a/arai60/merge-two-binary-trees/step1.py b/arai60/merge-two-binary-trees/step1.py new file mode 100644 index 0000000..5e59d36 --- /dev/null +++ b/arai60/merge-two-binary-trees/step1.py @@ -0,0 +1,40 @@ +# 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 +class Solution: + def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]: + if not root1 and not root2: return None + if not root1: return deepcopy(root2) + if not root2: return deepcopy(root1) + + merged_root = TreeNode(root1.val + root2.val) + def merge_trees_helper(root1: Optional[TreeNode], root2: Optional[TreeNode], merged_root: TreeNode) -> None: + if not root1 and not root2: return + if not root1: + merged_root.left = deepcopy(root2.left) + merged_root.right = deepcopy(root2.right) + return + if not root2: + merged_root.left = deepcopy(root1.left) + merged_root.right = deepcopy(root1.right) + return + + if root1.left or root2.left: + left_sum = 0 + if root1.left: left_sum += root1.left.val + if root2.left: left_sum += root2.left.val + merged_root.left = TreeNode(left_sum) + merge_trees_helper(root1.left, root2.left, merged_root.left) + + if root1.right or root2.right: + right_sum = 0 + if root1.right: right_sum += root1.right.val + if root2.right: right_sum += root2.right.val + merged_root.right = TreeNode(right_sum) + merge_trees_helper(root1.right, root2.right, merged_root.right) + + merge_trees_helper(root1, root2, merged_root) + return merged_root diff --git a/arai60/merge-two-binary-trees/step2.py b/arai60/merge-two-binary-trees/step2.py new file mode 100644 index 0000000..b2a4170 --- /dev/null +++ b/arai60/merge-two-binary-trees/step2.py @@ -0,0 +1,16 @@ +# 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 +class Solution: + def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]: + if not root1 and not root2: return None + if not root1: return deepcopy(root2) + if not root2: return deepcopy(root1) + + merged_root = TreeNode(root1.val + root2.val) + merged_root.left = self.mergeTrees(root1.left, root2.left) + merged_root.right = self.mergeTrees(root1.right, root2.right) + return merged_root diff --git a/arai60/merge-two-binary-trees/step2_nonrecursive.py b/arai60/merge-two-binary-trees/step2_nonrecursive.py new file mode 100644 index 0000000..2b99522 --- /dev/null +++ b/arai60/merge-two-binary-trees/step2_nonrecursive.py @@ -0,0 +1,41 @@ +# 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 +class Solution: + def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]: + if not root1 and not root2: return None + if not root1: return deepcopy(root2) + if not root2: return deepcopy(root1) + + merged_tree = TreeNode(root1.val + root2.val) + nodes_to_visit = [(root1, root2, merged_tree)] + while nodes_to_visit: + root1, root2, merged_root = nodes_to_visit.pop() + if not root1 and not root2: continue + if not root1: + merged_root.left = deepcopy(root2.left) + merged_root.right = deepcopy(root2.right) + continue + if not root2: + merged_root.left = deepcopy(root1.left) + merged_root.right = deepcopy(root1.right) + continue + + if root1.left or root2.left: + left_sum = 0 + if root1.left: left_sum += root1.left.val + if root2.left: left_sum += root2.left.val + merged_root.left = TreeNode(left_sum) + nodes_to_visit.append((root1.left, root2.left, merged_root.left)) + + if root1.right or root2.right: + right_sum = 0 + if root1.right: right_sum += root1.right.val + if root2.right: right_sum += root2.right.val + merged_root.right = TreeNode(right_sum) + nodes_to_visit.append((root1.right, root2.right, merged_root.right)) + + return merged_tree diff --git a/arai60/merge-two-binary-trees/step3.py b/arai60/merge-two-binary-trees/step3.py new file mode 100644 index 0000000..b2a4170 --- /dev/null +++ b/arai60/merge-two-binary-trees/step3.py @@ -0,0 +1,16 @@ +# 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 +class Solution: + def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]: + if not root1 and not root2: return None + if not root1: return deepcopy(root2) + if not root2: return deepcopy(root1) + + merged_root = TreeNode(root1.val + root2.val) + merged_root.left = self.mergeTrees(root1.left, root2.left) + merged_root.right = self.mergeTrees(root1.right, root2.right) + return merged_root