Conversation
|
|
||
| return dummy.left | ||
| ``` | ||
| * `side` の設定には`setattr` を使うのが望ましい? |
There was a problem hiding this comment.
あ、これは黒魔術の類で、黒魔術の中ではましくらいの話と思ってください。
__ から始まるマジックメソッドは可能ならば直接呼びたくはないです。
There was a problem hiding this comment.
つまり、partial(output.__setattr__, child) という風にすると引数を与えて呼び出すことで、狙った場所に値をセットする関数が作れます。
ただ、それならば partial(setattr, output, child) のほうがよいだろうくらいのことです。
nanae772
left a comment
There was a problem hiding this comment.
お疲れ様です、いろいろな解法を調べて解かれていて非常に勉強になりました。
| - それぞれの木のノード数をn,mとする | ||
| * 再帰による深さ優先探索(DFS)の前順(pre-order)走査 | ||
| * 葉ノードまで降りてから、ボトムアップで木を構築 | ||
| * 2つの二分木で片方しか葉が存在しない場合、元の二分木の葉オブジェクトをそのまま使っているのに少し違和感がある |
There was a problem hiding this comment.
おっしゃる通り確かに違和感がありますね。下の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つの二分木のデータ構造をそれぞれ配列に変換し値を保持して先頭から配列同士を足していく方針 |
There was a problem hiding this comment.
例えば以下のような二分木は
[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': |
There was a problem hiding this comment.
新しめの書き方になりますが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')) |
There was a problem hiding this comment.
LやR、分かりやすくて良いですね。
以前同じような用途で文字列の"left"や"right"を使っていて、タイプミス対策にenumを使うことを勧めていただいたことがありました。
1文字ならタイプミスもそこまで心配しなくて良いかもですが、ご参考まで。
h1rosaka/arai60#27 (comment)
| if not root1 and not root2: | ||
| return None | ||
|
|
||
| sentinel = TreeNode(0) |
There was a problem hiding this comment.
sentinel、使い方的には node1 / node2 が None だったときに使うデフォルト値的なイメージかと思いますが、一般的な用語の使い方とはずれるように感じます。
https://en.wikipedia.org/wiki/Sentinel_value
であればまだ dummy か、もっというと
if not node1:
node1 = TreeNode(0)
if not node2:
node2 = TreeNode(0)で軽くコメントしてくほうが素直かなと感じました。
617. Merge Two Binary Trees
次回予告: 703. Kth Largest Element in a Stream