Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 164 additions & 0 deletions 111/111. Minimum Depth of Binary Tree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# [111. Minimum Depth of Binary Tree](https://leetcode.com/problems/minimum-depth-of-binary-tree/description/)
## Step1
### 問題意図の考察
- 問題文の確認
- 2分木が与えられ、その最小の深さを見つけよ。
- 最小の深さ:根nodeから最も近いleaf nodeまで到達するパスに含まれるノード数
- 一昨日の問題で、「木の高さ・深さ」復習不足で明確に言葉にできなかった。反省。
- 例2の場合、最小1で返せないのはleaf nodeではないからか

- 制約の確認
- The number of nodes in the tree is in the range [0, 10^5]. (100,000)
- -1000 <= Node.val <= 1000
- 最大10万、O(n log n)でもいいが、O(n)がベター

- 問題意図
- rootから最も近いleaf nodeまでに含まれるnodeの数を返す.
- leaf nodeは、left == null AND right == null

### 解法を考える。
- maximumと同じようにDFS実行すると、勿体無いのでBFSで最小深さがいいのか
- DFSでもmin(minDepth(root->left), minDepth(root->right))で求められるのか
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DFSでも、根からの深さを持ちながら全探索を行い、葉に到達するたびにmin_depth = min(min_depth, depth)と更新することで最小深さを求められますね。

- これ片側nullの時、1を返してしまう気がする
- 分からなかったので、回答を見る。
- https://github.com/5103246/LeetCode_Arai60/pull/21

初回の回答
```cpp
#include <queue>
#include <utility>

class Solution {
public:
int minDepth(TreeNode* root) {
if (root == nullptr) {
return 0;
}

std::queue<std::pair<TreeNode*, int>> q;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

変数名qについて、自分はfrontiersにするかなと思いました。これから見る予定のものを詰め込んでいくという感覚で使っています。
LeetCodeの回答のような短い処理では変数名qでも問題ないと思いますが、コーディング練習の観点から語彙の提案という目的でコメントしました。

q.emplace(root, 1);

while (!q.empty()) {
auto [node, depth] = q.front();
q.pop();

if (node->left == nullptr && node->right == nullptr) {
return depth;
}

if (node->left != nullptr) {
q.emplace(node->left, depth + 1);
}
if (node->right != nullptr) {
q.emplace(node->right, depth + 1);
}
}

return 0;
}
};

```

### コメント
- https://en.cppreference.com/w/cpp/container/queue.html
- queueの復習 以下コピー

```cpp
#include <cassert>
#include <iostream>
#include <queue>

int main() {
std::queue<int> q;

q.push(0); // back pushes 0
q.push(1); // q = 0 1
q.push(2); // q = 0 1 2
q.push(3); // q = 0 1 2 3

assert(q.front() == 0);
assert(q.back() == 3);
assert(q.size() == 4);

q.pop();
assert(q.size() == 3);

std::cout << "q: ";
for (; !q.empty(); q.pop())
std::cout << q.front() << ' ';
std::cout << '\n';
assert(q.size() == 0);
}

```

## Step2
- ドキュメント
- 構造化束縛に関して
- ドキュメントを確認したが、よく理解できなかった。
- q.front()自体は参照だけど、一度[e]というローカル変数へコピーされる
- nodeとdepthはそのコピーeのメンバへの参照
- queueの中身には結びついていない。こんな理解でいいのかな
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

それで問題ないかと思います。
auto& で受けると中への参照です。

- https://en.cppreference.com/w/cpp/language/structured_binding.html?utm_source
- https://devblogs.microsoft.com/oldnewthing/20201014-00/?p=104367&utm_source
- 日本語で再度確認
- https://cpprefjp.github.io/lang/cpp17/structured_bindings.html?utm_source


- 他の方のコードを読む
- C++
- https://github.com/nktr-cp/leetcode/pull/23/commits/89f89e3a299793d659c51608abb88ac78d1ad5e5
- https://github.com/5103246/LeetCode_Arai60/pull/21/commits/91982dbf3d97e8cda66c9c98581a0c7fa6d41184
- https://github.com/irohafternoon/LeetCode/pull/24/commits/dbfa048eee71878803336be5049cac289369f3d5

- Python
- https://github.com/nanae772/leetcode-arai60/pull/22/commits/b1014637825bd38227854616e206b4fb14a7da00#diff-c788c611274db6a06c7e00a85483754293185d8070e7b0ace89d2360e40d1fbb

- 他の解法
```cpp
#include <vector>

class Solution {
public:
int minDepth(TreeNode* root) {
if (root == nullptr) {
return 0;
}

std::vector<TreeNode*> current_nodes;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

current_nodesだと個人的に情報量が少ないと感じるので、自分ならnodes_in_depthやfrontiersなどと名付けます。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@docto-rin
frontiersの命名をする人が多いですね。参考にさせて頂きます。

current_nodes.push_back(root);
int depth = 1;

while (!current_nodes.empty()) {
std::vector<TreeNode*> next_nodes;

for (TreeNode* node : current_nodes) {
if (node->left == nullptr && node->right == nullptr) {
return depth;
}
if (node->left != nullptr) {
next_nodes.push_back(node->left);
}
if (node->right != nullptr) {
next_nodes.push_back(node->right);
}
}

++depth;
current_nodes.swap(next_nodes);
}

return 0;
}
};

```

## Step3
1. 14min
2. 13min
3. 11min
4. 11min
5. 9min