diff --git a/617_merge_two_binary_trees/memo.md b/617_merge_two_binary_trees/memo.md new file mode 100644 index 0000000..a28da54 --- /dev/null +++ b/617_merge_two_binary_trees/memo.md @@ -0,0 +1,43 @@ +# 617. Merge Two Binary Trees + +https://leetcode.com/problems/merge-two-binary-trees/description/ + +## Comments + +### step1 + +* 最初 iterative DFS (`nodes_pairs = [(root1, root2)]` のような stack) で書こうとしたが、結局、今の node だけに注目していると、どの node の child なのか管理しないといけない気がして、再帰に方針変更 + * limit が 2000 なので、まあ recursionlimit を変更するかは環境次第か +* 10:00 くらいで `Solution1` まで書いてみた。`new_node.left = merge_trees_helper(node1.left, node2.left)` のあたりで None に left / right をやって runtime error になった。この時点で、node1 が None、node2 が None、両方 None でないの 3 パターンがあり、これごとに条件分岐するの非常に面倒だなと思う +* get_left もしくは三項演算子を使って node1_left みたいなのを定義はできるが、node1_left, node2_left. node1_right, node2_right すべてやるの面倒だな… +* ここまでで 13:00 以上経過していたので一旦打ち切り +* -> あとで一応ベタ書きしてみた…これはひどい (`Solution2`)。二分木ではなく四分木だったらもっとひどい。 + +### step2 + +* https://github.com/hayashi-ay/leetcode/pull/12/files + * なるほど既存の木を編集していく想定だった? + * ああそうか片方が None のときは merge する必要がなく、もう片方を返せばいいだけか。 + * そうすると merge するのは、いずれも None でないケースに限定されるので書きやすい + * ここなんとなく書きたくはなるが確かに `if root1 is None` でカバーされているから不要ではある + * `çopy.deepcopy` で非破壊的にできる。コピーに時間かかるがいいかは微妙だけど。 + +```python + if root1 is None and root2 is None: + return None +``` + +* https://github.com/nittoco/leetcode/pull/30/files#r1693985989 + * これでシンプルに書ける +* https://github.com/nittoco/leetcode/pull/30/files#r1693945861 + * 仕事を押し付ける、押し付けないの議論がよく理解できていないのでまた読む。 + +### step3 + +* 2:00 前後。とりあえずこれが一番シンプルな解法だと思われる。 +* ここは却って読みにくい気もするので、あまり使わないほうがいいかな。 + +```python + # if root1 is None or root2 is None: + # return root1 or root2 +``` diff --git a/617_merge_two_binary_trees/step1.py b/617_merge_two_binary_trees/step1.py new file mode 100644 index 0000000..897a047 --- /dev/null +++ b/617_merge_two_binary_trees/step1.py @@ -0,0 +1,53 @@ +# 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 +# Runtime error +class Solution1: + def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]: + def merge_trees_helper(node1, node2): + if node1 is None and node2 is None: + return None + node1_val = node1.val if node1 is not None else 0 + node2_val = node2.val if node2 is not None else 0 + new_node = TreeNode(node1_val + node2_val) + new_node.left = merge_trees_helper(node1.left, node2.left) + new_node.right = merge_trees_helper(node1.right, node2.right) + return new_node + + return merge_trees_helper(root1, root2) + + +# ベタ書き。これはひどい +# Accepted +class Solution2: + def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]: + def merge_trees_helper(node1, node2): + if node1 is None and node2 is None: + return None + node1_val = node1.val if node1 is not None else 0 + node2_val = node2.val if node2 is not None else 0 + new_node = TreeNode(node1_val + node2_val) + if node1 is not None and node2 is not None: + node1_left = node1.left + node1_right = node1.right + node2_left = node2.left + node2_right = node2.right + elif node1 is None: + node1_left = None + node1_right = None + node2_left = node2.left + node2_right = node2.right + elif node2 is None: + node1_left = node1.left + node1_right = node1.right + node2_left = None + node2_right = None + + new_node.left = merge_trees_helper(node1_left, node2_left) + new_node.right = merge_trees_helper(node1_right, node2_right) + return new_node + + return merge_trees_helper(root1, root2) diff --git a/617_merge_two_binary_trees/step2.py b/617_merge_two_binary_trees/step2.py new file mode 100644 index 0000000..ce6dc88 --- /dev/null +++ b/617_merge_two_binary_trees/step2.py @@ -0,0 +1,19 @@ +# 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 root1 is None and root2 is None: + return None + if root1 is None: + return root2 + if root2 is None: + return root1 + + new_root = TreeNode(root1.val + root2.val) + new_root.left = self.mergeTrees(root1.left, root2.left) + new_root.right = self.mergeTrees(root1.right, root2.right) + return new_root diff --git a/617_merge_two_binary_trees/step3.py b/617_merge_two_binary_trees/step3.py new file mode 100644 index 0000000..ff8ea4c --- /dev/null +++ b/617_merge_two_binary_trees/step3.py @@ -0,0 +1,19 @@ +# 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 root1 is None or root2 is None: + # return root1 or root2 + if root1 is None: + return root2 + if root2 is None: + return root1 + + new_root = TreeNode(root1.val + root2.val) + new_root.left = self.mergeTrees(root1.left, root2.left) + new_root.right = self.mergeTrees(root1.right, root2.right) + return new_root