diff --git a/arai60/minimum-depth-of-binary-tree/README.md b/arai60/minimum-depth-of-binary-tree/README.md new file mode 100644 index 0000000..ef81817 --- /dev/null +++ b/arai60/minimum-depth-of-binary-tree/README.md @@ -0,0 +1,41 @@ +## 考察 +- 初見の問題 +- 昨日の問題が maximum depth だったのに対して minimum depth +- 方針 + - DFS + - 帰りがけ + - left subtreeとright subtreeのdepthのminを取って1を足して返却 + - 再帰の深さについて考える必要 + - 最大10^5のため、デフォルトのPythonの環境では厳しい(一応LeetCode上ならOK) + - 帰りがけDFSを非再帰で書くのはつらい + - 行きがけ + - 全探索しながらleafのときに答えを更新 + - BFS + - level順に見ていくので、leafが見つかったら答えをreturnしてOK +- 上記を考慮して、Step1はBFSでやる +- あとは実装 + +## Step1 +- BFSで実装 +- nodeがNoneのときにはキューに入れない実装もできるが、複雑度(if文)が2つ増えるためこちらの書き方を選択 +- time: O(n), space: O(n) + +## Step2 +- 帰りがけDFSと行きがけDFSでも書いてみる + - `step2_postorder_dfs.py` + - `step2_preorder_dfs.py` +- 実装のしやすさでは再帰DFS +- 他の人のPRを検索してみる + - BFSはキューを2つ作る書き方も主流みたい + - https://github.com/fhiyo/leetcode/pull/24#discussion_r1648682841 + - この書き方はtorusさんのword ladderでのbidirectional bfsの解法のところでも見た + - 前から順番に取り出せればいいのでキューである必要はなさそう + - float('inf')について + - https://github.com/fhiyo/leetcode/pull/24#discussion_r1648673169 + - is と == の違い + - https://github.com/sakupan102/arai60-practice/pull/23#discussion_r1591177498 + +## Step3 +- 1回目: 1m16s +- 2回目: 1m03s +- 3回目: 1m01s diff --git a/arai60/minimum-depth-of-binary-tree/step1.py b/arai60/minimum-depth-of-binary-tree/step1.py new file mode 100644 index 0000000..76c9a76 --- /dev/null +++ b/arai60/minimum-depth-of-binary-tree/step1.py @@ -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: + nodes_to_visit = deque([(root, 1)]) + while nodes_to_visit: + node, depth = nodes_to_visit.popleft() + if not node: continue + if not node.left and not node.right: + return depth + nodes_to_visit.append((node.left, depth + 1)) + nodes_to_visit.append((node.right, depth + 1)) + + return 0 diff --git a/arai60/minimum-depth-of-binary-tree/step2_postorder_dfs.py b/arai60/minimum-depth-of-binary-tree/step2_postorder_dfs.py new file mode 100644 index 0000000..fbace4d --- /dev/null +++ b/arai60/minimum-depth-of-binary-tree/step2_postorder_dfs.py @@ -0,0 +1,20 @@ +# 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 not root: + return 0 + if not root.left and not root.right: + return 1 + + min_depth = math.inf + if root.left: + min_depth = min(min_depth, self.minDepth(root.left)) + if root.right: + min_depth = min(min_depth, self.minDepth(root.right)) + + return min_depth + 1 diff --git a/arai60/minimum-depth-of-binary-tree/step2_preorder_dfs.py b/arai60/minimum-depth-of-binary-tree/step2_preorder_dfs.py new file mode 100644 index 0000000..eabf4a0 --- /dev/null +++ b/arai60/minimum-depth-of-binary-tree/step2_preorder_dfs.py @@ -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 not root: + return 0 + + min_depth = math.inf + nodes_to_visit = [(root, 1)] + while nodes_to_visit: + node, depth = nodes_to_visit.pop() + if not node.left and not node.right: + min_depth = min(min_depth, depth) + + if node.left: + nodes_to_visit.append((node.left, depth + 1)) + if node.right: + nodes_to_visit.append((node.right, depth + 1)) + + return min_depth diff --git a/arai60/minimum-depth-of-binary-tree/step3.py b/arai60/minimum-depth-of-binary-tree/step3.py new file mode 100644 index 0000000..10a18fe --- /dev/null +++ b/arai60/minimum-depth-of-binary-tree/step3.py @@ -0,0 +1,17 @@ +# 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: + nodes_to_visit = deque([(root, 1)]) + while nodes_to_visit: + node, depth = nodes_to_visit.popleft() + if not node: continue + if not node.left and not node.right: + return depth + nodes_to_visit.append((node.left, depth + 1)) + nodes_to_visit.append((node.right, depth + 1)) + return 0