-
Notifications
You must be signed in to change notification settings - Fork 0
111. Minimum Depth of Binary Tree #23
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,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 |
| 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: | ||
| 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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| 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 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: | ||
|
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. わりと好みの範囲だと思いますが、自分はleftとrightの処理を逆にします。ツリーの探索は左から見るのが自然だと思うので。今のコードだと右から探索しています。
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. ああ、たしかにそうですね。そこまで気が回っていませんでした、ありがとうございます。 |
||
| nodes_to_visit.append((node.left, depth + 1)) | ||
| if node.right: | ||
| nodes_to_visit.append((node.right, depth + 1)) | ||
|
|
||
| return min_depth | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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)]) | ||
|
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. 好みの問題かもしれませんが、nodes_to_visitよりも、queueの中身をより反映させるために、nodes_and_depthに自分ならするかもしれません。 |
||
| 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 | ||
|
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. rootが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. ありがとうございます。おっしゃる通りだと思いました。 class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
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))
raise ValueError("unreachable")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 comment
The reason will be displayed to describe this comment to others. Learn more.
見やすさのために書いているかもしれませんが、ここは
min_depth = self.minDepth(root.left)でも通りそうですね。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.
たしかにそれでもいいですね。
自分は関数型言語でいうところのfoldのイメージで書いてました。
単位元で初期化して、二項関数で一つにまとめていくイメージです。