-
Notifications
You must be signed in to change notification settings - Fork 0
111. Minimum Depth of Binary Tree.md #40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,233 @@ | ||
| ### Step1 | ||
|
|
||
| - 最初、こう間違えた | ||
| - 入力が空の考慮をしなかったのはダメだったが、空の時の出力が0というのもなんか微妙だな | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def minDepth(self, node: Optional[TreeNode]) -> int: | ||
| if not node: | ||
| return inf | ||
| if not node.left and not node.right: | ||
| return 1 | ||
| return min(self.minDepth(node.left), self.minDepth(node.right)) + 1 | ||
| ``` | ||
|
|
||
| - infはあんまり使いたくないなあ | ||
| - float型が出るのと、意図がわかりにくいかも | ||
| - 思ったよりちょっとだけややこしくなった | ||
| - 再帰の回数は、枝の数だけある。 | ||
| - 10^5が最大で、環境によっては超えるかも | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def minDepth(self, node: Optional[TreeNode]) -> int: | ||
| if not node: | ||
| return 0 | ||
| if not node.left and not node.right: | ||
| return 1 | ||
| if not node.right: | ||
| return self.minDepth(node.left) + 1 | ||
| if not node.left: | ||
| return self.minDepth(node.right) + 1 | ||
| return min(self.minDepth(node.left), self.minDepth(node.right)) + 1 | ||
| ``` | ||
|
|
||
| - ループにするため、まずは末尾再帰(ぽい形)に | ||
| - 別にnot_reached_leafとかで変数も作れるけど、まあinfで妥協 | ||
|
|
||
| ```python | ||
|
|
||
| class Solution: | ||
| def minDepth(self, root: Optional[TreeNode]) -> int: | ||
| if not root: | ||
| return 0 | ||
| depth_min = inf | ||
|
|
||
| def min_depth_helper(node, depth): | ||
| nonlocal depth_min | ||
| if not node: | ||
| return | ||
| if not node.left and not node.right: | ||
| depth_min = min(depth_min, depth) | ||
| min_depth_helper(node.left, depth + 1) | ||
| min_depth_helper(node.right, depth + 1) | ||
|
|
||
| min_depth_helper(root, 1) | ||
| return depth_min | ||
| ``` | ||
|
|
||
| - 上の処理をループに | ||
| - leafの判定は切り出した方がわかりやすいかも | ||
| - タプルの中身2つだとdataclass作るまでもないかなあ | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def is_leaf(self, node: [TreeNode]) -> bool: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
(その場合だと、nodeにNoneが来る想定になるので、TreeNodeの方がいいですね)
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 型注釈の書き方がよくわかっておらず変な書き方をしてしまいました🙏 |
||
| return not node.left and not node.right | ||
|
|
||
| def minDepth(self, root: Optional[TreeNode]) -> int: | ||
| if not root: | ||
| return 0 | ||
| stack = [(root, 1)] | ||
| result = inf | ||
| while stack: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. この解法だけstackといった命名を用いているのが気になりました。他に合わせてdepth_minやnode_and_depthでもいいのかとおもいました。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ありがとうございます そうですね、ちょっと不親切だったかもしれません |
||
| node, depth = stack.pop() | ||
| if not node: | ||
| continue | ||
| if self.is_leaf(node): | ||
| result = min(depth, result) | ||
| continue | ||
| stack.append((node.left, depth + 1)) | ||
| stack.append((node.right, depth + 1)) | ||
| return result | ||
|
|
||
| ``` | ||
|
|
||
| - BFSでも書いてみる | ||
|
|
||
| ```python | ||
|
|
||
| class Solution: | ||
| def is_leaf(self, node: [TreeNode]) -> bool: | ||
| return not node.left and not node.right | ||
|
|
||
| def minDepth(self, root: Optional[TreeNode]) -> int: | ||
| if not root: | ||
| return 0 | ||
| current_level = [(root, 1)] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. level(depth?)の他にノードが入っているので、命名がやや気になるかもです。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. なるほど、levelで終わってるとdepthしか入ってないように確かに見えるかもですね。 |
||
| result = inf | ||
| while True: | ||
| if not current_level: | ||
| return result | ||
| next_level = [] | ||
| for node, depth in current_level: | ||
| if not node: | ||
| continue | ||
| if self.is_leaf(node): | ||
| result = min(depth, result) | ||
| next_level.append((node.left, depth + 1)) | ||
| next_level.append((node.right, depth + 1)) | ||
| current_level = next_level | ||
| ``` | ||
|
|
||
| ### Step2 | ||
|
|
||
| https://github.com/seal-azarashi/leetcode/pull/21 | ||
|
|
||
| - BFSはlevel別に配列管理した方が好み | ||
| - BFSでループが回る場合の処理を書くなら、無限ループの方が意図がわかりやすい、確かに | ||
|
|
||
| https://github.com/goto-untrapped/Arai60/pull/46 | ||
|
|
||
| - DFSだったら枝狩りできるの気がつかなかった〜 | ||
| - こういうの自分気づかないがち | ||
| - while Trueを嫌がるコメント、他の方のでも見たことあるが、個人的に賛成はできない。while(条件)の条件部分を、if not 条件 breakって中に書けば同じなので | ||
| - ループの停止が決定不能問題だから、ループそのもの自体そもそも気をつけようというのはあるかも | ||
| - infをINITIALIZEDにするのはなるほどと思ったが、それなら別変数で定義する方がわかりやすいかもなあ | ||
| - rootがnullの判定をやめて最後にreturn 0するのはあまり好みではない。return 0がなんの時なのかがわかりにくいため | ||
|
|
||
| https://github.com/Ryotaro25/leetcode_first60/pull/24 | ||
|
|
||
| - nullの場合を探索しない再帰も実装してもいいかも | ||
|
|
||
| https://github.com/TORUS0818/leetcode/pull/24 | ||
|
|
||
| - 単位元が0のminをカスタム定義は、中身がわけわかんなくなるかも? | ||
|
|
||
| https://github.com/hroc135/leetcode/pull/21/files | ||
|
|
||
| - BFS、よく考えたらdepthはタプルに入れなくてもdepth+=1でよかった | ||
| - depth += 1をループの最初に書くか、最後に書くか、迷う | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 私は最後派ですが、どちらでもいいのではないでしょうか。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @oda さんはちなみにどういう理由で最後派ですか? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. C++ だったら気持ちとして、 for (int depth = 1; !current_level_nodes.empty(); ++depth) {
...
current_level_nodes.swap(next_level_nodes);
}じゃないですかね。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. なるほど、C++だとそういう書き方ができるんですね。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 要するに、depth はループのテーマのようなもので、++depth というのがループを次の行に行くための処理であると見て、ループの中では depth は最後に変化するほうが理解しやすいだろうということです。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. そうですね、テーマが最初にいきなり変化するのは確かにちょっと追いにくいかもですね(ループを引き継ぎだと考えると) |
||
| - メインの処理で、最初にないと読んでて不安になる? | ||
| - でも重要な変数が最初にいきなり変わるのは混乱する? | ||
| - う〜む難しい | ||
| - 償却計算量、CSライザップでやったが、ちゃんとした式を追ってなかったので勉強になった | ||
|
|
||
| https://github.com/Yoshiki-Iwasa/Arai60/pull/25/files | ||
|
|
||
| - .leftと.rightをループで回してもいいのか、迷う | ||
|
|
||
| - 枝刈りBFSを書いてみる | ||
| - 試しに今回はnullは突っ込まないように | ||
|
|
||
| ```python | ||
|
|
||
| class Solution: | ||
| def is_leaf(self, node: [TreeNode]) -> bool: | ||
| return not node.left and not node.right | ||
|
|
||
| def minDepth(self, root: Optional[TreeNode]) -> int: | ||
| if not root: | ||
| return 0 | ||
| current_level_nodes = [root] | ||
| depth = 0 | ||
| while True: | ||
| depth += 1 | ||
| next_level_nodes = [] | ||
| for node in current_level_nodes: | ||
| if self.is_leaf(node): | ||
| return depth | ||
| if node.left: | ||
| next_level_nodes.append(node.left) | ||
| if node.right: | ||
| next_level_nodes.append(node.right) | ||
| current_level_nodes = next_level_nodes | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. current_level_nodesとnext_level_nodeは一つに纏めてもいいなかと思いました。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 全部読んでみないとわからないという事ですかね。 |
||
| ``` | ||
|
|
||
| - infの代わりに、まだ見てないかを別変数で定義 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 宗派にもよりそうですが、Pythonだとやり過ぎじゃないですかねー?C, C++歴が長い人は別変数にする方を好みそうな気もします。知らないですが。 |
||
| - やりすぎ? | ||
|
|
||
| ```python | ||
|
|
||
| class Solution: | ||
| def is_leaf(self, node: [TreeNode]) -> bool: | ||
| return not node.left and not node.right | ||
|
|
||
| def minDepth(self, root: Optional[TreeNode]) -> int: | ||
| if not root: | ||
| return 0 | ||
| node_with_depth = [(root, 1)] | ||
| reached_leaf_so_far = False | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. なんか変数名が分かりづらいです。is_first, first_nodeあたりはどうですかね? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nittocoさん、変数名に たとえば、
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ありがとうございます。 |
||
| result = None | ||
| while node_with_depth: | ||
| node, depth = node_with_depth.pop() | ||
| if not node: | ||
| continue | ||
| if self.is_leaf(node): | ||
| if reached_leaf_so_far and depth >= result: | ||
| continue | ||
| result = depth | ||
| reached_leaf_so_far = True | ||
|
Comment on lines
+197
to
+201
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if self.is_leaf(node) and (result is None or depth < result):
result = depth
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. それも考えたんですけど、Noneと整数を同じ変数にするのがどうかなと思ったんですよね(考えすぎですかね) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 192行目でresult = Noneとなっていますが…
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. すみません、書いた時のことを思い出すとそういう判断基準ではなかったですね。 |
||
| node_with_depth.append((node.right, depth + 1)) | ||
| node_with_depth.append((node.left, depth + 1)) | ||
| return result | ||
| ``` | ||
|
|
||
| ## Step3 | ||
|
|
||
| - BFSが自然かなあ | ||
|
|
||
| ```python | ||
|
|
||
| class Solution: | ||
| def is_leaf(self, node: [TreeNode]) -> bool: | ||
| return not node.left and not node.right | ||
|
|
||
| def minDepth(self, root: Optional[TreeNode]) -> int: | ||
| if not root: | ||
| return 0 | ||
| current_level_nodes = [root] | ||
| depth = 0 | ||
| while True: | ||
| depth += 1 | ||
| next_level_nodes = [] | ||
| for node in current_level_nodes: | ||
| if not node: | ||
| continue | ||
| if self.is_leaf(node): | ||
| return depth | ||
| next_level_nodes.append(node.left) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 自分は |
||
| next_level_nodes.append(node.right) | ||
| current_level_nodes = next_level_nodes | ||
| ``` | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
これ、まとまりますかね?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
あ、すみません、勘違いです。min ですね。