Skip to content

Conversation

@skypenguins
Copy link
Owner

@skypenguins skypenguins commented Sep 7, 2025

617. Merge Two Binary Trees

次回予告: 703. Kth Largest Element in a Stream

@skypenguins skypenguins self-assigned this Sep 7, 2025

return dummy.left
```
* `side` の設定には`setattr` を使うのが望ましい?
Copy link

Choose a reason for hiding this comment

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

あ、これは黒魔術の類で、黒魔術の中ではましくらいの話と思ってください。
__ から始まるマジックメソッドは可能ならば直接呼びたくはないです。

Copy link

Choose a reason for hiding this comment

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

つまり、partial(output.__setattr__, child) という風にすると引数を与えて呼び出すことで、狙った場所に値をセットする関数が作れます。
ただ、それならば partial(setattr, output, child) のほうがよいだろうくらいのことです。

Copy link

@nanae772 nanae772 left a comment

Choose a reason for hiding this comment

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

お疲れ様です、いろいろな解法を調べて解かれていて非常に勉強になりました。

- それぞれの木のノード数をn,mとする
* 再帰による深さ優先探索(DFS)の前順(pre-order)走査
* 葉ノードまで降りてから、ボトムアップで木を構築
* 2つの二分木で片方しか葉が存在しない場合、元の二分木の葉オブジェクトをそのまま使っているのに少し違和感がある

Choose a reason for hiding this comment

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

おっしゃる通り確かに違和感がありますね。下のDeepCopyを行うヘルパー関数を使う方法以外だと、以下のようにもできそうです(番兵を使うともう少し見通しがよくなるかもしれません)。

class Solution:
    def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        def get_left(node: TreeNode | None) -> TreeNode | None:
            return node.left if node is not None else None
        def get_right(node: TreeNode | None) -> TreeNode | None:
            return node.right if node is not None else None

        if root1 is None and root2 is None:
            return None

        root1_value = root1.val if root1 is not None else 0
        root2_value = root2.val if root2 is not None else 0
        merged = TreeNode(root1_value + root2_value)

        merged.left = self.mergeTrees(get_left(root1), get_left(root2))
        merged.right = self.mergeTrees(get_right(root1), get_right(root2))

        return merged

## Step1
* 2つの二分木をBFSで探索しながら、mergeした二分木を構築する方針
- 片方にしか葉が存在しない場合、2つの葉の位置が揃わないが処理が思い浮かばず次の方針に切り替える
* 2つの二分木のデータ構造をそれぞれ配列に変換し値を保持して先頭から配列同士を足していく方針

Choose a reason for hiding this comment

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

例えば以下のような二分木は
[1, 2, None, 3, None, None, None, 4]
という形に変換するイメージで認識合っていますでしょうか?

        1
       /
     2
    /
  3
 /
4

もしそうであればこのような直線的な木が深さdになったときに配列サイズも2^dで増えていくため、メモリが厳しくなりそうだなと思いました

merged_node = TreeNode(node1.val + node2.val)

# 親ノードの適切な位置に設定
if side == 'L':

Choose a reason for hiding this comment

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

新しめの書き方になりますがmatch caseを使ってもいいかなと思いました
https://docs.python.org/ja/3.10/reference/compound_stmts.html#the-match-statement

parent.right = merged_node

# 子ノードをキューに追加
nodes.append((node1.left, node2.left, merged_node, 'L'))

Choose a reason for hiding this comment

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

LやR、分かりやすくて良いですね。

以前同じような用途で文字列の"left"や"right"を使っていて、タイプミス対策にenumを使うことを勧めていただいたことがありました。
1文字ならタイプミスもそこまで心配しなくて良いかもですが、ご参考まで。
h1rosaka/arai60#27 (comment)

if not root1 and not root2:
return None

sentinel = TreeNode(0)

Choose a reason for hiding this comment

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

sentinel、使い方的には node1 / node2 が None だったときに使うデフォルト値的なイメージかと思いますが、一般的な用語の使い方とはずれるように感じます。

https://en.wikipedia.org/wiki/Sentinel_value

であればまだ dummy か、もっというと

            if not node1:
                node1 = TreeNode(0)
            if not node2:
                node2 = TreeNode(0)

で軽くコメントしてくほうが素直かなと感じました。

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants