-
Notifications
You must be signed in to change notification settings - Fork 0
102. Binary Tree Level Order Traversal #27
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,34 @@ | ||
| ## 考察 | ||
| - 過去に解いたことあり | ||
| - 方針 | ||
| - BFS | ||
| - BFSはlevelごとに見ていくのでシンプルに解ける | ||
| - 実装としては、キューを1つ使う方法と2つ使う方法が考えられる | ||
| - DFS | ||
| - 一応、levelを追跡すればOK | ||
| - でも、DFSでやるメリットはないと思われる | ||
| - まずは、BFSのキューを1つだけ用意する方法で実装 | ||
|
|
||
| ## Step1 | ||
| - BFSで実装 | ||
| - time: O(n), space: O(n) | ||
|
|
||
| ## Step2 | ||
| - キューを2つ用意する方法でも実装 | ||
| - `step2_bfs_two_queues.cpp` | ||
| - 特にキューである必要もないので、vector2つでも実装 | ||
| - `step2_bfs_two_vectors.cpp` | ||
| - 練習のためにDFSでも実装 | ||
| - `stpe2_dfs.cpp` | ||
| - 他の人のPRを検索 | ||
| - https://github.com/fhiyo/leetcode/pull/28 | ||
| - append_if_existsはいいなあと思った | ||
| - https://github.com/Mike0121/LeetCode/pull/7 | ||
| - currentについて | ||
| - https://github.com/Mike0121/LeetCode/pull/7#discussion_r1587660995 | ||
| - たしかに `level_values` だけでも通じるかも | ||
|
|
||
| ## Step3 | ||
| - 1回目: 3m27s | ||
| - 2回目: 3m12s | ||
| - 3回目: 3m05s |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| /** | ||
| * Definition for a binary tree node. | ||
| * struct TreeNode { | ||
| * int val; | ||
| * TreeNode *left; | ||
| * TreeNode *right; | ||
| * TreeNode() : val(0), left(nullptr), right(nullptr) {} | ||
| * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} | ||
| * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} | ||
| * }; | ||
| */ | ||
| class Solution { | ||
| public: | ||
| vector<vector<int>> levelOrder(TreeNode* root) { | ||
| if (!root) return vector<vector<int>>(); | ||
| vector<vector<int>> answer; | ||
| queue<TreeNode*> nodes_to_visit; | ||
|
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. step2_bfs_two_vectors のように、レベルごとに vector を作ったほうが処理が分かりやすいと思いました。 また、変数名の to_visit の部分は、有益な情報が含まれていないように感じました。 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. ありがとうございます。レベルごとに vector を作る実装を第一選択肢として考えるようにしてみます。 |
||
| nodes_to_visit.push(root); | ||
| while (!nodes_to_visit.empty()) { | ||
| int level_size = nodes_to_visit.size(); | ||
|
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.
|
||
| vector<int> current_level_values; | ||
|
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. 個人的には values_in_level としたいですが、 current_level_values でも acceptable だと思います。 |
||
| for (int i = 0; i < level_size; i++) { | ||
| TreeNode* node = nodes_to_visit.front(); | ||
| nodes_to_visit.pop(); | ||
| current_level_values.push_back(node->val); | ||
| if (node->left) nodes_to_visit.push(node->left); | ||
| if (node->right) nodes_to_visit.push(node->right); | ||
| } | ||
| answer.push_back(move(current_level_values)); | ||
| } | ||
| return answer; | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| /** | ||
| * Definition for a binary tree node. | ||
| * struct TreeNode { | ||
| * int val; | ||
| * TreeNode *left; | ||
| * TreeNode *right; | ||
| * TreeNode() : val(0), left(nullptr), right(nullptr) {} | ||
| * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} | ||
| * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} | ||
| * }; | ||
| */ | ||
| class Solution { | ||
| public: | ||
| vector<vector<int>> levelOrder(TreeNode* root) { | ||
| if (!root) return vector<vector<int>>(); | ||
| vector<vector<int>> answer; | ||
| queue<TreeNode*> nodes_to_visit; | ||
|
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. 一つのキューで順不同で push() と pop() をしたりするわけではく、先頭から順にノードを舐められれば十分なため、 queue にする必要が無いように感じました。 step2_bfs_two_vectors のように、 vector 2 つで十分だと思います。 |
||
| nodes_to_visit.push(root); | ||
| while (!nodes_to_visit.empty()) { | ||
| vector<int> current_level_values; | ||
| queue<TreeNode*> next_level_nodes; | ||
| int level_size = nodes_to_visit.size(); | ||
| for (int i = 0; i < level_size; i++) { | ||
|
Comment on lines
+22
to
+23
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. たしかに |
||
| TreeNode* node = nodes_to_visit.front(); | ||
| nodes_to_visit.pop(); | ||
| current_level_values.push_back(node->val); | ||
| if (node->left) next_level_nodes.push(node->left); | ||
| if (node->right) next_level_nodes.push(node->right); | ||
| } | ||
| answer.push_back(move(current_level_values)); | ||
| nodes_to_visit = 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. = だとコピーが走ります。 std::swap() したほうが処理が軽くなると思います。 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. std::vector::swap のほうが動くバージョン広いですかね?
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. コピー走りますね。。まだ意識が甘いようです、ありがとうございます。 std::swap, std::vector::swap ともにC++98から使用可能で、std::swap は内部で std::vector::swap を呼び出すようなのでどちらを使っても良さそうです。
https://en.cppreference.com/w/cpp/container/vector/swap |
||
| } | ||
| return answer; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| /** | ||
| * Definition for a binary tree node. | ||
| * struct TreeNode { | ||
| * int val; | ||
| * TreeNode *left; | ||
| * TreeNode *right; | ||
| * TreeNode() : val(0), left(nullptr), right(nullptr) {} | ||
| * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} | ||
| * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} | ||
| * }; | ||
| */ | ||
| class Solution { | ||
| public: | ||
| vector<vector<int>> levelOrder(TreeNode* root) { | ||
| if (!root) return vector<vector<int>>(); | ||
| vector<vector<int>> answer; | ||
| vector<TreeNode*> nodes_to_visit; | ||
| nodes_to_visit.push_back(root); | ||
| while (!nodes_to_visit.empty()) { | ||
| vector<int> current_level_values; | ||
| vector<TreeNode*> next_level_nodes; | ||
| for (TreeNode* node : nodes_to_visit) { | ||
| current_level_values.push_back(node->val); | ||
| if (node->left) next_level_nodes.push_back(node->left); | ||
| if (node->right) next_level_nodes.push_back(node->right); | ||
| } | ||
| answer.push_back(move(current_level_values)); | ||
| nodes_to_visit = next_level_nodes; | ||
| } | ||
| return answer; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| /** | ||
| * Definition for a binary tree node. | ||
| * struct TreeNode { | ||
| * int val; | ||
| * TreeNode *left; | ||
| * TreeNode *right; | ||
| * TreeNode() : val(0), left(nullptr), right(nullptr) {} | ||
| * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} | ||
| * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} | ||
| * }; | ||
| */ | ||
| class Solution { | ||
| public: | ||
| vector<vector<int>> levelOrder(TreeNode* root) { | ||
| if (!root) return vector<vector<int>>(); | ||
| vector<vector<int>> answer; | ||
| stack<pair<TreeNode*, int>> nodes_to_visit; | ||
| nodes_to_visit.push({root, 0}); | ||
| while (!nodes_to_visit.empty()) { | ||
| auto [node, level] = nodes_to_visit.top(); | ||
| nodes_to_visit.pop(); | ||
| if (answer.size() == level) { | ||
|
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. answer に push_back() する処理を省くため、 map<int, vector> level_to_nodes; として、最後に answer に詰め替えるのも良いかなと思ったのですが、処理がやや重くなるのが微妙にも感じました。 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. なるほど。この考えはありませんでした。 |
||
| answer.push_back({node->val}); | ||
| } else { | ||
| answer[level].push_back(node->val);; | ||
| } | ||
|
|
||
| if (node->right) nodes_to_visit.push({node->right, level + 1}); | ||
| if (node->left) nodes_to_visit.push({node->left, level + 1}); | ||
| } | ||
| return answer; | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| /** | ||
| * Definition for a binary tree node. | ||
| * struct TreeNode { | ||
| * int val; | ||
| * TreeNode *left; | ||
| * TreeNode *right; | ||
| * TreeNode() : val(0), left(nullptr), right(nullptr) {} | ||
| * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} | ||
| * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} | ||
| * }; | ||
| */ | ||
| class Solution { | ||
| public: | ||
| vector<vector<int>> levelOrder(TreeNode* root) { | ||
| if (!root) return {}; | ||
| vector<vector<int>> answer; | ||
| queue<TreeNode*> nodes_to_visit; | ||
| nodes_to_visit.push(root); | ||
| while (!nodes_to_visit.empty()) { | ||
| int level_size = nodes_to_visit.size(); | ||
| vector<int> level_values; | ||
|
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. この書き方は思いつきませんでした。勉強になります、ありがとうございます。 |
||
| for (int i = 0; i < level_size; i++) { | ||
| auto node = nodes_to_visit.front(); | ||
| nodes_to_visit.pop(); | ||
| level_values.push_back(node->val); | ||
| if (node->left) nodes_to_visit.push(node->left); | ||
| if (node->right) nodes_to_visit.push(node->right); | ||
| } | ||
| answer.push_back(move(level_values)); | ||
| } | ||
| return answer; | ||
| } | ||
| }; | ||
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.
見ました。既出のコメント以外の点では、特に問題ないかと思いました。