-
Notifications
You must be signed in to change notification settings - Fork 0
15. 3Sum #74
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
Open
Ryotaro25
wants to merge
2
commits into
main
Choose a base branch
from
blind9
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
15. 3Sum #74
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| class Solution { | ||
| public: | ||
| vector<vector<int>> threeSum(vector<int>& nums) { | ||
| if (nums.empty()) { | ||
| return {}; | ||
| } | ||
| set<vector<int>> unique_triplets; | ||
| for (int i = 0; i < nums.size(); i++) { | ||
| for (int j = 0; j < nums.size(); j++) { | ||
| for (int k = 0; k < nums.size(); k++) { | ||
| if (i == j || j == k || k == i) { | ||
| continue; | ||
| } | ||
| if (nums[i] + nums[j] + nums[k] == 0) { | ||
| vector<int> triplet = {nums[i], nums[j], nums[k]}; | ||
| sort(triplet.begin(), triplet.end()); | ||
| unique_triplets.insert(triplet); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return vector<vector<int>>(unique_triplets.begin(), unique_triplets.end()); | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| ## ステップ1 | ||
| Brute forceは比較的簡単に思いついた | ||
| 3つの数字を追うように3つのループを使い、合計が0の場合に | ||
| vectorに入れてsortしそれをsetに入れることで重複を消す | ||
| 時間計算量はO(n^3 * log n) | ||
| brute_force.cppに実装 | ||
|
|
||
| nums[i]とnums[j]が決まれば残りの数が決まる. | ||
| 残りの数をcomplimentとすると | ||
| nums[i] + nums[j] + compliment = 0 | ||
| compliment = -nums[i] - nums[j] | ||
|
|
||
| jをループでまわす際に、setを使ってすでに通りすぎたnums[j]を記録していく | ||
| complimentがset内に入っていれば、合計して0になる組が存在するということ | ||
| これをvectorに入れてsortしそれをsetに入れることで重複を消す | ||
| 時間計算量はO(n^2 * log n) | ||
| 3000 = 3 * 10^3 | ||
| ≒ 9 * 10^6 * 3 | ||
| ≒ 10^7なので許容ないか | ||
| acceptまで20分 | ||
|
|
||
| ## ステップ2 | ||
| 変数名を微調整 | ||
|
|
||
| 最初に入力値をsortしてしまう方法もある。 | ||
| https://leetcode.com/problems/3sum/editorial/ | ||
| sort.cppに実装 | ||
|
|
||
| 3つの数のうちどれか一つは必ず負の数であることを利用する | ||
| ひとつ目の数字が決まったら、その次の数字と最後の数字を見ていく | ||
| 合計が0になるまで前後から狭める | ||
|
|
||
| i == 0の場合とnums[i] != nums[i - 1]の場合に呼び出すものが同じなので | ||
| 纏めるか迷うところ。比較している対象は異なる | ||
|
|
||
| この解法が最も素直か | ||
|
|
||
| ## ステップ3 | ||
| **3回書き直しやりましょう、といっているのは、不自然なところや負荷の高いところは覚えられないからです。** | ||
|
|
||
| ## 他の解法 | ||
|
|
||
|
|
||
| ## Discordなど | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| class Solution { | ||
| public: | ||
| vector<vector<int>> threeSum(vector<int>& nums) { | ||
| sort(nums.begin(), nums.end()); | ||
| vector<vector<int>> triplets; | ||
| for (int i = 0; i < nums.size(); i++) { | ||
| if (nums[i] > 0) { | ||
| break; | ||
| } | ||
| if (i == 0) { | ||
| FindTriplet(nums, i, triplets); | ||
| continue; | ||
| } | ||
| if (nums[i] != nums[i - 1]) { | ||
| FindTriplet(nums, i, triplets); | ||
| } | ||
| } | ||
| return triplets; | ||
| } | ||
|
|
||
| private: | ||
| void FindTriplet(vector<int>& nums, int index, vector<vector<int>>& triplets) { | ||
| int left = index + 1; | ||
| int right = nums.size() - 1; | ||
| while (left < right) { | ||
| int sum = nums[index] + nums[left] + nums[right]; | ||
| if (sum < 0) { | ||
| 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. sum < 0 と sum > 0 の場合は continue し、 sum == 0 の場合のネストを下げたほうが読みやすいと思います。 |
||
| } else if (sum > 0) { | ||
| right--; | ||
| } else { | ||
| triplets.push_back({nums[index], nums[left], nums[right]}); | ||
| 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. do while 文で回すと 1 行減ります。読みやすさはあまり変わらないかもしれません。 |
||
| while (left < right && nums[left] == nums[left - 1]) { | ||
| left++; | ||
| } | ||
| right--; | ||
| while (left < right && nums[right] == nums[right + 1]) { | ||
| right--; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| class Solution { | ||
| public: | ||
| vector<vector<int>> threeSum(vector<int>& nums) { | ||
| set<vector<int>> unique_triplets; | ||
| // 3組の内ひとつ目の数字をユニークにするために使用 | ||
| set<int> first_nums; | ||
| for (int i = 0; i < nums.size(); i++) { | ||
| if (first_nums.contains(nums[i])) { | ||
| continue; | ||
| } | ||
| first_nums.insert(nums[i]); | ||
|
|
||
| // nums[i]に対応する(nums[j], complement)のペアを探すために | ||
| // 既にnums[j]として通りすぎた数字を記録する。 | ||
| set<int> seen; | ||
| for (int j = i + 1; j < nums.size(); j++) { | ||
| int complement = -nums[i] - nums[j]; | ||
| if (!seen.contains(complement)) { | ||
| seen.insert(nums[j]); | ||
| continue; | ||
| } | ||
|
|
||
| vector<int> triplet = {nums[i], nums[j], complement}; | ||
| sort(triplet.begin(), triplet.end()); | ||
| unique_triplets.insert(triplet); | ||
| } | ||
| } | ||
|
|
||
| // vectorに変換して返す | ||
| return vector<vector<int>>(unique_triplets.begin(), unique_triplets.end()); | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| class Solution { | ||
| public: | ||
| vector<vector<int>> threeSum(vector<int>& nums) { | ||
| set<vector<int>> unique_triplets; | ||
| set<int> used_first_nums; | ||
| for (int i = 0; i < nums.size(); i++) { | ||
| if (used_first_nums.contains(nums[i])) { | ||
| continue; | ||
| } | ||
| used_first_nums.insert(nums[i]); | ||
|
|
||
| set<int> seen; | ||
| for (int j = i + 1; j < nums.size(); j++) { | ||
| int complement = -nums[i] - nums[j]; | ||
| if (!seen.contains(complement)) { | ||
| seen.insert(nums[j]); | ||
| continue; | ||
| } | ||
|
|
||
| vector<int> triplet = {nums[i], nums[j], complement}; | ||
| sort(triplet.begin(), triplet.end()); | ||
| unique_triplets.insert(triplet); | ||
| } | ||
| } | ||
|
|
||
| return vector<vector<int>>(unique_triplets.begin(), unique_triplets.end()); | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| class Solution { | ||
| public: | ||
| vector<vector<int>> threeSum(vector<int>& nums) { | ||
| set<vector<int>> unique_triplets; | ||
| set<int> used_first_nums; | ||
| for (int i = 0; i < nums.size(); i++) { | ||
| if (used_first_nums.contains(nums[i])) { | ||
| continue; | ||
| } | ||
| used_first_nums.insert(nums[i]); | ||
|
|
||
| set<int> seen; | ||
| for (int j = i + 1; j < nums.size(); j++) { | ||
| int complement = -nums[i] - nums[j]; | ||
| if (!seen.contains(complement)) { | ||
| seen.insert(nums[j]); | ||
| continue; | ||
| } | ||
| vector<int> triplet = {nums[i], nums[j], complement}; | ||
| sort(triplet.begin(), triplet.end()); | ||
| unique_triplets.insert(triplet); | ||
| } | ||
| } | ||
| return vector<vector<int>>(unique_triplets.begin(), unique_triplets.end()); | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| class Solution { | ||
| public: | ||
| int maxProduct(vector<int>& nums) { | ||
| if (nums.empty()) { | ||
| return 0; | ||
| } | ||
| int max_product = numeric_limits<int>::min(); | ||
| for (int i = 0; i < nums.size(); i++) { | ||
| int temp = 1; | ||
| for (int j = i; j < nums.size(); j++) { | ||
| temp *= nums[j]; | ||
| max_product = max(max_product, temp); | ||
| } | ||
| } | ||
| return max_product; | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| ## ステップ1 | ||
| まず思いついた解法はbrute forceで愚直に積を求める方法 | ||
| これだと時間計算量は、O(n^2)となる | ||
| nums.lengthは2 * 10 ^ 4なので4 * 10 ^ 8 C++だとギリギリ1秒ないに処理できそう | ||
|
|
||
| 各ステップで最大になるタイミングを追いかける | ||
| ・あるnums[i]でリセットする場合(負の数を奇数個含む場合はnums[i]の方が大きくなることがある) | ||
| ・正の数ばかりがsubarrayに含まれる場合 | ||
| ・負の数偶数個含む場合 | ||
| 単に正の数だけ追うのではなく負の数も追いかけると1ループで見つけられそう | ||
| 時間計算量はO(n) | ||
| 空間計算量はO(1) | ||
|
|
||
| acceptまで12分 | ||
|
|
||
| 配列が空の場合にreturn 0とする。 | ||
| 本当はありえない数字を返したかった。エラーメッセージを表示するなどでも良さそう。 | ||
|
|
||
| ## ステップ2 | ||
| step1の変数名が長いので、変更 | ||
|
|
||
| maxとminの使い方変更 | ||
| initializer listsを使うことで複数の値でも使うことができる | ||
| https://cplusplus.com/reference/algorithm/max/ | ||
|
|
||
| ## ステップ3 | ||
| **3回書き直しやりましょう、といっているのは、不自然なところや負荷の高いところは覚えられないからです。** | ||
|
|
||
| ## 他の解法 | ||
| 負の数が偶数個あると最大になりうる特性を活かして途中でswapすることで | ||
| 自分のstep1で行った3パターンから2パターンへ比較回数を減らすことができる(step2_2で実装) | ||
| これは初見で思いつくことが難しそうなので愚直に比較したい | ||
| https://leetcode.com/problems/maximum-product-subarray/solutions/48230/possibly-simplest-solution-with-o-n-time-complexity/ | ||
|
|
||
| ## Discorなど | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| class Solution { | ||
| public: | ||
| int maxProduct(vector<int>& nums) { | ||
| if (nums.empty()) { | ||
| return 0; | ||
| } | ||
| int max_product = nums[0]; | ||
| int max_product_so_far = nums[0]; | ||
| int min_product_so_far = nums[0]; | ||
| for (int i = 1; i < nums.size(); i++) { | ||
| int temp_max_so_far = max(nums[i], max(max_product_so_far * nums[i], min_product_so_far * nums[i])); | ||
| min_product_so_far = min(nums[i], min(max_product_so_far * nums[i], min_product_so_far * nums[i])); | ||
| max_product_so_far = temp_max_so_far; | ||
| max_product = max(max_product, max_product_so_far); | ||
| } | ||
|
|
||
| return max_product; | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| class Solution { | ||
| public: | ||
| int maxProduct(vector<int>& nums) { | ||
| if (nums.empty()) { | ||
| return 0; | ||
| } | ||
| int max_product = nums[0]; | ||
| int current_max = nums[0]; | ||
| int current_min = nums[0]; | ||
| for (int i = 1; i < nums.size(); i++) { | ||
| // current_maxの数字は次の行で使うので一旦退避 | ||
| int temp = max({nums[i], current_max * nums[i], current_min * nums[i]}); | ||
| current_min = min({nums[i], current_max * nums[i], current_min * nums[i]}); | ||
|
|
||
| current_max = temp; | ||
| max_product = max(max_product, current_max); | ||
| } | ||
|
|
||
| return max_product; | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| class Solution { | ||
| public: | ||
| int maxProduct(vector<int>& nums) { | ||
| if (nums.empty()) { | ||
| return 0; | ||
| } | ||
| int max_product = nums[0]; | ||
| int max_product_so_far = nums[0]; | ||
| int min_product_so_far = nums[0]; | ||
| for (int i = 1; i < nums.size(); i++) { | ||
| if (nums[i] < 0) { | ||
| swap(max_product_so_far, min_product_so_far); | ||
| } | ||
| max_product_so_far = max(nums[i], max_product_so_far * nums[i]); | ||
| min_product_so_far = min(nums[i], min_product_so_far * nums[i]); | ||
| max_product = max(max_product, max_product_so_far); | ||
| } | ||
|
|
||
| return max_product; | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| class Solution { | ||
| public: | ||
| int maxProduct(vector<int>& nums) { | ||
| if (nums.empty()) { | ||
| return 0; | ||
| } | ||
|
|
||
| int max_product = nums[0]; | ||
| int current_max = nums[0]; | ||
| int current_min = nums[0]; | ||
| for (int i = 1; i < nums.size(); i++) { | ||
| int temp = max({nums[i], current_max * nums[i], current_min * nums[i]}); | ||
| current_min = min({nums[i], current_max * nums[i], current_min * nums[i]}); | ||
|
|
||
| current_max = temp; | ||
| max_product = max(max_product, current_max); | ||
| } | ||
|
|
||
| return max_product; | ||
| } | ||
| }; |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
nums が非 const 参照だと、読み手にとって中で変更されるのだと思わせてしまうと思います。 nums は変更されないため、 const 参照で渡すことをおすすめします。
LeetCode が指定した関数宣言については、仕方ないと思います。