Skip to content
Open
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
129 changes: 129 additions & 0 deletions 111. Minimum Depth of Binary Tree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
1st

BFS で探索して、一番早く子ノードがないノードの階層を返せば良い。

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

depth = 1
queue = deque([(root, 1)]) # ツリーと階層
while queue:
node, level = queue.popleft()
if node.left is None and node.right is None:
return level
if node.left:
queue.append((node.left, level + 1))
if node.right:
queue.append((node.right, level + 1))

```

2nd
再帰の DFS で書く。気をつけることとしては再帰が深くなりすぎてスタックオーバーフロー(RecursionError)にならないかどうか。
今回は制約上 10^5 なので、デフォルトの再帰の深さだとエラーになるが、leetcode は自動で再帰の深さを増やしているため、この問題は発生しない。
とはいえ、「この環境なら大丈夫」なコードは後々問題になることがあるので、実務なら上の BFS のコードを書くと思う。

```python
class Solution:
def minDepth(self, root: TreeNode) -> int:
if root is None:
return 0
if root.left is None and root.right is None:
return 1
Comment on lines +34 to +35
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 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
```

インナー関数を使った再帰

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

スタックを用いた再帰
これだと全部の葉を調べる必要があるので、これをするなら最初の BFS を用いたコードを書くなあ。
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

スタックを用いたDFSですね
スタックDFSも再帰DFSもどちらも全ノードを探索することになると思います


```python
class Solution:
def minDepth(self, root: TreeNode) -> int:
if root is None:
return 0

min_depth = -1
stack = [(root, 1)]
while stack:
node, level = stack.pop()
if node.left is None and node.right is None:
min_depth = min(min_depth, level)
if node.left:
stack.append((node.left, level + 1))
if node.right:
stack.append((node.right, level + 1))
return min_depth

```

https://github.com/nittoco/leetcode/pull/40#discussion_r1869636610さんを見て、タプルで階層を管理しなくても良いことに気づいたので
自分でもその方式で実装する。
階層ごとに処理する今回の方法の場合、各階層でやりたい処理が追加である場合に対応しやすいが
タプルで管理する方法は階層の深さを明示しなくても常に今の深さが分かる点がある。
今回だと深さを知りたいだけなので、趣味の範囲かなと思った。
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

趣味の範囲なんですが、個人的な意見として、queue の中身のデータの整合性が取れているということは、読んでいる人からすると全部読み終わらないと分からないからです。書いている人は分かるわけですが。
つまり、一つの変数に、2つの違う種類のものを入れておいて、その境界を個数で管理しているわけですよね。

リスト2つ使って this_level, next_level を入れ替えていくという方法もあります。

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.

たしかに読み手からすると全部読み終わらないと分からないですね。

リスト2つ使って this_level, next_level を入れ替えていくという方法もあります。

こちらもstep4で書いてみます。


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

depth = 1
queue = deque([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.

すでに指摘されていますが、自分もここはqueueを使う必要がない点が気になりました

while queue:
for _ in range(len(queue)):
node = queue.popleft()
if node.left is None and node.right is None:
return depth
if node.left:
queue.append((node.left))
if node.right:
queue.append((node.right))
depth += 1
```

3rd
BFS を用いたコード
個人的には、タプルで管理するほうが、階層が分かりやすいと思った。

```python
class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
nodes_and_levels = deque([(root, 1)]) # ノードと階層
while node_and_levels:
node, level = node_and_levels.popleft()
if node.left is None and node.right is None:
return level
if node.left:
node_and_levels.append((node.left, level + 1))
if node.right:
node_and_levels.append((node.right, level + 1))
```