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

- https://discord.com/channels/1084280443945353267/1196472827457589338/1237988315781664770
> はい。再帰とスタックの書き換えくらいだと私も思います。しかし、この二つの変換が息を吐くようにできるとだいぶ分かっている感じがするので大事だと思います。

> そうですね。木の高さを求めるときには、上から数字を配っていくか、下から集めてくるかの2方向があって、それぞれ再帰で書くか、スタックとループで書くか、がありますね。

- sol1.py: トップダウン + ループ(BFS)
- 早期終了でき、深すぎる入力を避けられる。
- これが一番良いのでは?
- sol2.py: ボトムアップ + 再帰(DFS)
- 深い入力があった場合にオーバーフロー
- sol3.py: トップダウン + 再帰(DFS)
- 根からの情報を配りやすい(パスの条件が追加されるなど)
- 深い入力があった場合にオーバーフロー(上と同様)
- sol4.py: ボトムアップ + ループ(DFS / スタック)
- postorderで探索したいけど再帰を避けたい場合に使える
- もっとスラスラ書けるようになりたい

## BFS / DFS
- **BFS(幅優先)**: 根から浅い順に探索。最初に見つけた葉が最小深さなので「葉を見つけたら即 return」ができる(`sol1.py`)。
- **DFS(深さ優先)**: 全探索しつつ最小を取るか、ボトムアップで子の答えを集約する(`sol2.py`, `sol3.py`, `sol4.py`)。

## トップダウン / ボトムアップ(木DPの向き)
- **トップダウン**: 引数で深さを配る(`dfs(node, depth)` みたいに進む)。葉で答えを更新する(`sol3.py`)。
- **ボトムアップ**: 子の答えを先に確定してから親を計算する(`sol2.py`, `sol4.py`)。

24 changes: 24 additions & 0 deletions 111/sol1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from collections import deque


# Definition for a binary tree node.
# 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
frontier = deque()
frontier.append((1, root))
while frontier:
depth, node = frontier.popleft()
if node.right is None and node.left is None:
return depth
for child in (node.left, node.right):
if child is None:
continue
frontier.append((depth + 1, child))
raise RuntimeError("unreachable")
18 changes: 18 additions & 0 deletions 111/sol2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Definition for a binary tree node.
# 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
if root.right is None and root.left is None:
return 1
min_depth = float("inf")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ここの初期値はどんな感じで決められましたか?

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.

intのinfがないので、floatのinfで代用しました
(質問の意図に合っているか分かりませんが)

for child in (root.right, root.left):
if child is None:
continue
min_depth = min(min_depth, self.minDepth(child) + 1)
return min_depth
24 changes: 24 additions & 0 deletions 111/sol3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Definition for a binary tree node.
# 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
min_depth = float("inf")

def traverse(node, depth):
nonlocal min_depth
if node.left is None and node.right is None:
min_depth = min(min_depth, depth)
return
for child in (node.left, node.right):
if child is None:
continue
traverse(child, depth + 1)

traverse(root, 1)
return min_depth
36 changes: 36 additions & 0 deletions 111/sol4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from collections import deque


# Definition for a binary tree node.
# 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
node_to_depth = {}
frontier = deque()
frontier.append((root, False))
while frontier:
node, is_visited = frontier.pop()
if node is None:
continue
if not is_visited:
frontier.append((node, True))
frontier.append((node.left, False))
frontier.append((node.right, False))
continue
depth_l = node_to_depth.get(node.left, None)
depth_r = node_to_depth.get(node.right, None)
if depth_l is None and depth_r is None:
node_to_depth[node] = 1
elif depth_l is None:
node_to_depth[node] = depth_r + 1
elif depth_r is None:
node_to_depth[node] = depth_l + 1
else:
node_to_depth[node] = min(depth_l, depth_r) + 1
return node_to_depth[root]