Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions arai60/merge-two-binary-trees/README.md
Original file line number Diff line number Diff line change
@@ -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で実装してみる
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://discord.com/channels/1084280443945353267/1201211204547383386/1218151037697917028
帰りの処理が書き込みだけならば、子供に書き込み先のポインタを渡して書き込んでもらう手があります。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。確認します。


## Step3
- 1回目: 1m36s
- 2回目: 1m15s
- 3回目: 1m17s
40 changes: 40 additions & 0 deletions arai60/merge-two-binary-trees/step1.py
Original file line number Diff line number Diff line change
@@ -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
16 changes: 16 additions & 0 deletions arai60/merge-two-binary-trees/step2.py
Original file line number Diff line number Diff line change
@@ -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
41 changes: 41 additions & 0 deletions arai60/merge-two-binary-trees/step2_nonrecursive.py
Original file line number Diff line number Diff line change
@@ -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:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ちょっとif root1.left or root2.left:とif root1.left: left_sum += root1.left.valがifの処理が重複していて長いかなという気がしたので

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)

とか書き換えてみるとどうでしょうか

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

んー、if root1.left or root2.left:の条件を外すと両方Noneの場合でも値が0のノードを追加することになってしまうんですよね。。とはいえleftとrightに対して全く同じ処理をしているので関数化はした方が良さそうです。

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
16 changes: 16 additions & 0 deletions arai60/merge-two-binary-trees/step3.py
Original file line number Diff line number Diff line change
@@ -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