Skip to content

617. Merge Two Binary Trees#23

Open
tarinaihitori wants to merge 2 commits intomainfrom
617-merge-two-binary-trees
Open

617. Merge Two Binary Trees#23
tarinaihitori wants to merge 2 commits intomainfrom
617-merge-two-binary-trees

Conversation

@tarinaihitori
Copy link
Copy Markdown
Owner

「この関数は、root1 をただ読むだけだろう」と思い込んでいて、「マージの結果として新しいツリーを返すだけだろう」と予想している状態で、実際は root1 をガンガン上書きする関数が呼ばれたら、
後から root1 を再利用しようとしたときに予期せぬ値や構造になっていて「えっ、なんでツリーが書き換わってるの?」と驚くことになりそうだと思った。
もし破壊的に書くなら、
ライブラリのドキュメントに「破壊的です」と書くかな。
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

全く新しい木を構築していく方法もあると思います。step3のコードでも下記のようなケースにroot1とmergeTreesの返り値でポインタの共有部分があるとroot1への変更が返り値にも影響してしまう場合があるのは気をつけないといけないと思いました。pythonのポインタについて誤解していたらごめんなさい

root1 = TreeNode(1)
root2 = None
merged_tree = mergeTrees(root1, root2)
print(merged_tree.val)  # 1
root1.val += 1
print(merged_tree.val)  # 2

「この関数は、root1 をただ読むだけだろう」と思い込んでいて、「マージの結果として新しいツリーを返すだけだろう」と予想している状態で、実際は root1 をガンガン上書きする関数が呼ばれたら、
後から root1 を再利用しようとしたときに予期せぬ値や構造になっていて「えっ、なんでツリーが書き換わってるの?」と驚くことになりそうだと思った。
もし破壊的に書くなら、
ライブラリのドキュメントに「破壊的です」と書くかな。
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ruby では ! をつけることによって表現する流儀がありますね。Python では変数名に使えないですが。
https://www.ruby-lang.org/en/documentation/faq/7/#destructive-metho

merged_node.right = node2.right

return merged_root
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Python は、メンバ変数へのポインターが持てないので、どうしても繰り返し感がでますね。下のような方法は一応考えてみました。

class Solution:
    def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        roots = list(filter(None, [root1, root2]))
        if not roots:
            return None
        root = TreeNode()
        stack = [(root, roots)]
        while stack:
            dst_node, src_nodes = stack.pop()
            dst_node.val = sum(n.val for n in src_nodes)
            lefts = [n.left for n in src_nodes if n.left]
            if lefts:
                dst_node.left = TreeNode()
                stack.append((dst_node.left, lefts))
            rights = [n.right for n in src_nodes if n.right]
            if rights:
                dst_node.right = TreeNode()
                stack.append((dst_node.right, rights))
        return root

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

これも別に良いコードではないですが、C++ だとどこに書き込むかをスタックに積むことができるので、少し簡単になるのです。それを擬似的に Python で表現してみました。

from functools import partial

class Solution:
    def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        dummy = TreeNode()
        stack = [(partial(dummy.__setattr__, "left"), [root1, root2])]
        while stack:
            write_node, nodes = stack.pop()
            nodes = list(filter(None, nodes))
            if not nodes:
                continue
            val = sum(n.val for n in nodes)
            output = TreeNode(val)
            write_node(output)
            for child in ['left', 'right']:
                stack.append((partial(output.__setattr__, child), [n.__getattribute__(child) for n in nodes]))
        return dummy.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.

Comment on lines +96 to +99
if root1 is None:
return root2
if root2 is None:
return root1
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Step 3の方法は、入力を破壊はしていないものの、マージ後の木と入力の木でノードが共有される可能性があります。

@Yoshiki-Iwasa
Copy link
Copy Markdown

良さそうです!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants