diff --git a/memo.md b/memo.md index 4bd0397..9cba9ef 100644 --- a/memo.md +++ b/memo.md @@ -1 +1,160 @@ # Step1 + +## アプローチ + +* maximumdepthと同様に考えられそう + * recursion + * 左の部下には, 左の部下を頭として一番小さい深さを教えてもらう + * 右の部下には, 右の部下を頭として一番小さい深さを教えてもらう + * 自分は, 受け取った二つのうち小さい方+1が最小だと上司に伝える + * bfs + * 各レベルごとに見ていく + * 子を持たないノードができたら終了 + * dfs + * 子を持たないノードに到達した時に, minimum_depthを更新する +* 計算量は, O(N). ノード数をNとする +* recursionをする場合の最大再帰スタックはN + +## Code1-1 (Recursion) - solved 4:56 + +```python +from typing import Optional + + +# 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.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 + +``` + +## Code1-2 (DFS) - solved 2:40 + +```python +from typing import Optional + + +# 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 = [(root, 1)] + minimum_depth = float("inf") + while frontier: + node, depth = frontier.pop() + if node.left is None and node.right is None: + minimum_depth = min(minimum_depth, depth) + continue + if node.left is not None: + frontier.append((node.left, depth + 1)) + if node.right is not None: + frontier.append((node.right, depth + 1)) + return minimum_depth + +``` + +## Code1-3 (BFS) - solved 2:42 + +```python +from typing import Optional +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 + + depth = 0 + frontier = deque() + frontier.append(root) + while frontier: + num_cur_frontier = len(frontier) + depth += 1 + for _ in range(num_cur_frontier): + node = frontier.popleft() + if node.left is None and node.right is None: + return depth + if node.left is not None: + frontier.append(node.left) + if node.right is not None: + frontier.append(node.right) + + raise ValueError() + +``` + +# 他の人のコードやコメント集を見る + +今回からarai60完走者のを見ることにした + +* 1 - https://github.com/mamo3gr/arai60/pull/20/files + * BFS + * BFSで`deque`を使わない方法をやっている. + * 注目している主役がわかりやすい + * BFSのエラー文をどうするか迷って空白にしたが, `something went wrong`くらいアバウトでもいいのか + * `raise RuntimeError("You can not reach here. There is something wrong in the implementation")` + * RuntimeErrorを使うのは考えに及ばなかった + * DFS + * `root.left`と`root.right`をループで回している + * バイナリツリーじゃなくなった場合でも応用が効きそう + * 変数`is_leaf`とかにif文の条件をまとめたら読みやすくなりそう + * 再帰 + * `root.left`と`root.right`をループで回す方法を再帰でもやっている +* 2 - https://github.com/Satorien/LeetCode/pull/22/files + * 帰りがけをstackにしたものがコメントで紹介されていた + * https://github.com/potrue/leetcode/pull/22#discussion_r2112567800 + * 一般的にみんながstackで行うdfsは行きがけ + * 一方で, 一般的にみんなが再帰で行うdfsは帰りがけ +* 3 - https://github.com/ryoooooory/LeetCode/pull/25/files + * whileの中でループすることが決まっているので`while(true)`を使っていた + * そうしたら`raise RuntimeError`をしなくてよくなる +* 4 - https://github.com/naoto-iwase/leetcode/pull/21/files + * 再帰関数の終了処理と, そもそもの与えられた引数の確認が別なら内部関数で処理を分けるのが見やすそう + * BFSのやり方についてのコメントがあった + +* ちなみに, 多くの人は再帰=DFSという表記をしているが, 本PRでは, DFSはstackを使った再帰を表すこととする + +``` +あと、BFS をするのに +node_queue +num_node_in_level +で数を数えて、次のレベルに行くの、少しややこしいと思っています。データの整合性が取れているということは、読んでいる人からすると全部読み終わらないと分からないからです。書いている人は分かるわけですが。 +つまり、一つの変数に、2つの違う種類のものを入れておいて、その境界を個数で管理しているわけですよね。 +``` \ No newline at end of file diff --git a/step1-1_recursion.py b/step1-1_recursion.py new file mode 100644 index 0000000..217a9be --- /dev/null +++ b/step1-1_recursion.py @@ -0,0 +1,27 @@ +from typing import Optional + + +# 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.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 + \ No newline at end of file diff --git a/step1-2_dfs.py b/step1-2_dfs.py new file mode 100644 index 0000000..7f437c2 --- /dev/null +++ b/step1-2_dfs.py @@ -0,0 +1,28 @@ +from typing import Optional + + +# 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 = [(root, 1)] + minimum_depth = float("inf") + while frontier: + node, depth = frontier.pop() + if node.left is None and node.right is None: + minimum_depth = min(minimum_depth, depth) + continue + if node.left is not None: + frontier.append((node.left, depth + 1)) + if node.right is not None: + frontier.append((node.right, depth + 1)) + return minimum_depth \ No newline at end of file diff --git a/step1-3_bfs.py b/step1-3_bfs.py new file mode 100644 index 0000000..5400ee9 --- /dev/null +++ b/step1-3_bfs.py @@ -0,0 +1,34 @@ +from typing import Optional +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 + + depth = 0 + frontier = deque() + frontier.append(root) + while frontier: + num_cur_frontier = len(frontier) + depth += 1 + for _ in range(num_cur_frontier): + node = frontier.popleft() + if node.left is None and node.right is None: + return depth + if node.left is not None: + frontier.append(node.left) + if node.right is not None: + frontier.append(node.right) + + raise ValueError() + \ No newline at end of file diff --git a/step2-1_recursion.py b/step2-1_recursion.py new file mode 100644 index 0000000..b07ff6e --- /dev/null +++ b/step2-1_recursion.py @@ -0,0 +1,26 @@ +from typing import Optional + + +# 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 + + def helper_minDepth(node: TreeNode) -> int: + if node.left is None and node.right is None: + return 1 + if node.left is None: + return helper_minDepth(node.right) + 1 + if node.right is None: + return helper_minDepth(node.left) + 1 + return min(helper_minDepth(node.left), helper_minDepth(node.right)) + 1 + + return helper_minDepth(root) \ No newline at end of file diff --git a/step2-2_dfs.py b/step2-2_dfs.py new file mode 100644 index 0000000..7f437c2 --- /dev/null +++ b/step2-2_dfs.py @@ -0,0 +1,28 @@ +from typing import Optional + + +# 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 = [(root, 1)] + minimum_depth = float("inf") + while frontier: + node, depth = frontier.pop() + if node.left is None and node.right is None: + minimum_depth = min(minimum_depth, depth) + continue + if node.left is not None: + frontier.append((node.left, depth + 1)) + if node.right is not None: + frontier.append((node.right, depth + 1)) + return minimum_depth \ No newline at end of file diff --git a/step2-3_bfs.py b/step2-3_bfs.py new file mode 100644 index 0000000..8a1e2ac --- /dev/null +++ b/step2-3_bfs.py @@ -0,0 +1,32 @@ +from typing import Optional +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([root]) + depth = 1 + while True: + next_frontier = deque() + while frontier: + node = frontier.popleft() + if node.left is None and node.right is None: + return depth + if node.left is not None: + next_frontier.append(node.left) + if node.right is not None: + next_frontier.append(node.right) + frontier = next_frontier + depth += 1 + \ No newline at end of file diff --git a/step3-1_recursion.py b/step3-1_recursion.py new file mode 100644 index 0000000..ba8bdda --- /dev/null +++ b/step3-1_recursion.py @@ -0,0 +1,30 @@ +# 1st 2:10 +# 2nd 1:05 +# 3rd 1:03 + +from typing import Optional + + +# 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 + + def minDepth_helper(node): + if node.left is None and node.right is None: + return 1 + if node.left is None: + return minDepth_helper(node.right) + 1 + if node.right is None: + return minDepth_helper(node.left) + 1 + return min(minDepth_helper(node.left), minDepth_helper(node.right)) + 1 + + return minDepth_helper(root) \ No newline at end of file diff --git a/step3-2_dfs.py b/step3-2_dfs.py new file mode 100644 index 0000000..c031757 --- /dev/null +++ b/step3-2_dfs.py @@ -0,0 +1,31 @@ +# 1st 2:16 +# 2nd 1:24 +# 3rd 1:09 + +from typing import Optional + + +# 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 = [(root, 1)] + min_depth = float("inf") + while frontier: + node, depth = frontier.pop() + if node.left is None and node.right is None: + min_depth = min(min_depth, depth) + if node.left is not None: + frontier.append((node.left, depth + 1)) + if node.right is not None: + frontier.append((node.right, depth + 1)) + return min_depth \ No newline at end of file diff --git a/step3-3_bfs.py b/step3-3_bfs.py new file mode 100644 index 0000000..f93b00c --- /dev/null +++ b/step3-3_bfs.py @@ -0,0 +1,35 @@ +# 1st 2:44 +# 2nd 1:23 +# 3rd 1:32 + +from typing import Optional +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([root]) + current_depth = 1 + while True: + next_frontier = deque() + while frontier: + node = frontier.popleft() + if node.left is None and node.right is None: + return current_depth + if node.left is not None: + next_frontier.append(node.left) + if node.right is not None: + next_frontier.append(node.right) + frontier = next_frontier + current_depth += 1