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
72 changes: 72 additions & 0 deletions 111-Minimum-Depth-of-Binary-Tree/note.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# 111. Minimum Depth of Binary Tree

https://leetcode.com/problems/minimum-depth-of-binary-tree/description/

## step1(まず通す)

https://leetcode.com/problems/maximum-depth-of-binary-tree/description/ とほぼ同じ。

違う点は、一番深いところは全ノード見ないとがわからないが、一番浅いところは同じ高さごとに見ていって、最初に見つかった葉のところなのでそれ以降を見なくて済む。

再帰で自然に書くと全部見ることになる。

@h-masder h-masder Jul 2, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

一応ですが、再帰というより、深さ優先探索を再帰でやると、ですね。

(私はこういう書き方はあまりしませんが、) 幅優先探索を再帰で書くことですべてを探索しないようにすることはできます。

class Solution:
    def minDepth(self, root: Optional[TreeNode]) -> int:
        if root is None:
            return 0

        def min_depth_helper(nodes: List[TreeNode], depth) -> int:
            next_nodes = []
            for node in nodes:
                if node.left is None and node.right is None:
                    return depth + 1
                if node.left is not None:
                    next_nodes.append(node.left)
                if node.right is not None:
                    next_nodes.append(node.right)

            return min_depth_helper(next_nodes, depth + 1)

        return min_depth_helper([root], 0)

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.

ありがとうございます。そうですね、自分の中で明示的な区別ができてなくて自然にという言葉で流してしまってましたが、本来は再帰で書くことと深さ優先探索をすることは別のことですよね。
指摘してくださってありがとうございます。好みでなくてもそういう書き方ができるということ自体は考慮に入れた上で選べるようにします。


```python
class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
if root.left is None and root.right is None:
return 1
if root.left is None:
return self.minDepth(root.right) + 1
if root.right is None:
return self.minDepth(root.left) + 1
return min(self.minDepth(root.left), self.minDepth(root.right)) + 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

改行があったほうが見やすいかなと思いました。

    def minDepth(self, root: Optional[TreeNode]) -> int:
        if root is None:
            return 0

        if root.left is None and root.right is None:
            return 1

        if root.left is None:
            return self.minDepth(root.right) + 1

        if root.right is None:
            return self.minDepth(root.left) + 1

        return min(self.minDepth(root.left), self.minDepth(root.right)) + 1

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.

ありがとうございます。今回は確かにそうかもしれませんね。

```

例えば、

```txt
0
/ \
1 2
/\
...(めっちゃ深い)
```

みたいな時にはだいぶ計算量が違う。

逆に、root から唯一の葉まで一本道みたいなときは見るノード数が同じになる。

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.

どの葉も同じ深さにあるようなときも見るノード数は同じですね。


## step2(整形&他の人のコードを読む)

2点知りたいことがある

- [昨日のやつにいただいたコメント](https://github.com/MA-yo-TA/leetcode/pull/21#discussion_r3506905860) に関連して、next_layer の初期化は while の冒頭と nodes とセットでやるのとみなさんどちらで書いているのか
- https://github.com/shintaro1993/arai60/pull/26/changes
- この方は while の冒頭
- ついでに depth の更新は while の最後
- 自分としては「nodes があるなら一段加算」という気がするので while の判定の直後に書きたい気がしているが変な気もする
- while ループを return 以外で抜けることはないが、それを型チェッカーに示す方法としては何がいいのか。
- 関数の末尾でエラーを出す?
- raise RuntimeError("unreachable") しているもの
- https://github.com/tom4649/Coding/pull/20/changes#diff-974436ac64380be2414ffa842d4dc5dd641279483233dca84985f0deee4311e2R24
-

- https://github.com/tom4649/Coding/pull/20/changes#r2939305873
- min_depth の初期値を float("inf") としていて、「ここの初期値はどんな感じで決められましたか?」「intのinfがないので、floatのinfで代用しました(質問の意図に合っているか分かりませんが)」とあるが、「(int からキャストできる float における)min() の単位元だから」というのが意図に沿った回答だろうか?
- 単位元 `e` は、(Python 風にいうと)同じ型のオブジェクト `x` とその型の引数を二つ取る関数・メソッド・演算子 `f` に対して常に(どんな `x` でも) `f(e, x) = x` となるもの
- counter を += で増やしていくなら 0
- min なら float("inf")(か、絶対越えられない適当なデカい値)
- max なら float("-inf") か 0(対象が自然数の場合)
- メリットは初回の操作がおかしくならないので初回と2回目以降を同じように扱えること
- 自分にも「ある変数を2項演算によって更新していくとき、初期値はその演算の単位元であるのが好ましい」という感覚がある
- ただし、操作が行われなかったときに初期値をそのまま返すような場合は気をつけた方がいい。期待されている出力が異なることがあるので。
- https://github.com/garunitule/coding_practice/blob/main/Tree/111/memo.md
- ここにも初期値をどうするかの議論がある
- 2 << 30 や 1 << 30 が「絶対越えられない適当なデカい数」として上がっている

## step3(10分以内にさっとかける \* 3回)

結局ループでは最初から次のレイヤーを探しに行きたい気がして諸々の更新処理は全部最後にした。仕事の引き継ぎだとすると、朝来て「細かいところは昨日のやつ全部やっといてくれよ」と思いそう。

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://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0#heading=h.ydq9ulueycy9

に書いてある

自分が読むときの許容度は広く、書く時は自分なりの統一した狭い幅に収めるという非対称性も必要になるでしょう。スタイルガイドを強制することは普通はできないので、かなり広く読めるようにして、ただし、自分のこだわりはもっておくということが必要になります。

を参考にして読んでいます。また、許容度としては、やりたいこととコードの表現が一致しているかどうかを見ています。

@h-masder h-masder Jul 2, 2026

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://github.com/MA-yo-TA/leetcode/pull/21/changes#r3512713879

上記のやり方も許容される範囲に入っています。

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.

ありがとうございます。いろいろな書き方を読めるようになるためにも今後も他の方のコードをいろいろ読もうと思います。

加えて、前回と今回レビューいただいて、自分の好みを持つ(知る)ためには色々考えながら複数パターンをある程度の量書くことが必要だなと感じたのでそのへんもこの練習会で意識して取り組みます。

あとループの前に登場人物が全員見えてた方が落ち着く。
28 changes: 28 additions & 0 deletions 111-Minimum-Depth-of-Binary-Tree/step1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from typing import Optional


class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right


class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0

depth = 0
nodes = [root]
while nodes:
next_layer = []
depth += 1
for node in nodes:
if node.left is None and node.right is None:
return depth
if node.left is not None:
next_layer.append(node.left)
if node.right is not None:
next_layer.append(node.right)
nodes = next_layer
30 changes: 30 additions & 0 deletions 111-Minimum-Depth-of-Binary-Tree/step2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from typing import Optional


class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right


class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0

nodes = [root]
depth = 0
while nodes:
next_layer = []
depth += 1
for node in nodes:
if node.left is None and node.right is None:
return depth
if node.left is not None:
next_layer.append(node.left)
if node.right is not None:
next_layer.append(node.right)
nodes = next_layer

raise RuntimeError("unreachable")
31 changes: 31 additions & 0 deletions 111-Minimum-Depth-of-Binary-Tree/step3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from typing import Optional


class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right


class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0

nodes = [root]
next_layer = []
depth = 1
while nodes:
for node in nodes:
if node.left is None and node.right is None:
return depth
if node.left is not None:
next_layer.append(node.left)
if node.right is not None:
next_layer.append(node.right)
nodes = next_layer
next_layer = []
depth += 1

raise RuntimeError("unreachable")