diff --git a/111. Minimum Depth of Binary Tree.md b/111. Minimum Depth of Binary Tree.md new file mode 100644 index 0000000..35b8b60 --- /dev/null +++ b/111. Minimum Depth of Binary Tree.md @@ -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 + + 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 を用いたコードを書くなあ。 + +```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さんを見て、タプルで階層を管理しなくても良いことに気づいたので +自分でもその方式で実装する。 +階層ごとに処理する今回の方法の場合、各階層でやりたい処理が追加である場合に対応しやすいが +タプルで管理する方法は階層の深さを明示しなくても常に今の深さが分かる点がある。 +今回だと深さを知りたいだけなので、趣味の範囲かなと思った。 + +```python +class Solution: + def minDepth(self, root: Optional[TreeNode]) -> int: + if root is None: + return 0 + + depth = 1 + queue = deque([root]) + 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)) +```