-
Notifications
You must be signed in to change notification settings - Fork 0
238. Product of Array Except Self #67
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,30 @@ | ||
| # コンパイラの設定 | ||
| CXX = g++ | ||
| # コンパイルオプション | ||
| CXXFLAGS = -std=c++17 -Wall -Wextra -O2 -I/Library/Developer/CommandLineTools/SDKs/MacOSX15.2.sdk/usr/include/c++/v1/ | ||
|
|
||
| # 実行ファイル名 | ||
| TARGET = main | ||
| SRC = main.cpp | ||
| HDR = main.h | ||
|
|
||
| # オブジェクトファイル(.o)の名前 | ||
| OBJ = $(SRC:.cc=.o) | ||
|
|
||
| # デフォルトターゲット:実行ファイルを作成 | ||
| all: $(TARGET) | ||
|
|
||
| # 実行ファイルを作成するルール | ||
| $(TARGET): $(OBJ) | ||
| # オブジェクトファイルから実行ファイルを作成 | ||
| $(CXX) $(CXXFLAGS) -o $@ $^ | ||
|
|
||
| # .cc から .o を作成するルール | ||
| %.o: %.cc $(HDR) | ||
| # ソースコードをコンパイルしてオブジェクトファイルを生成 | ||
| $(CXX) $(CXXFLAGS) -c $< -o $@ | ||
|
|
||
| # クリーンアップターゲット:コンパイル生成物を削除 | ||
| clean: | ||
| # コンパイルで生成されたオブジェクトファイルと実行ファイルを削除 | ||
| rm -f $(OBJ) $(TARGET) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| #include "main.h" | ||
| #include <iostream> | ||
|
|
||
| // Solution::をつけないとグローバル関数となる | ||
| std::vector<int> Solution::productExceptSelf(std::vector<int>& nums) { | ||
| if (nums.size() == 0) { | ||
| return {}; | ||
| } | ||
| std::vector<int> products_except_self(nums.size(), 1); | ||
| int prefix_product = 1; | ||
| for (int i = 0; i < nums.size(); i++) { | ||
| products_except_self[i] *= prefix_product; | ||
| prefix_product *= nums[i]; | ||
| } | ||
|
|
||
| int suffix_product = 1; | ||
| for (int i = nums.size() - 1; i >= 0; i--) { | ||
| products_except_self[i] *= suffix_product; | ||
| suffix_product *= nums[i]; | ||
| } | ||
|
|
||
| return products_except_self; | ||
| } | ||
|
|
||
| int main() { | ||
| Solution solution; | ||
| std::vector<int> nums = {-1,1,0,-3,3}; | ||
| std::vector<int> products = solution.productExceptSelf(nums); | ||
| std::cout << "Output is: "; | ||
| for (int product : products) { | ||
| std::cout << product << " "; | ||
| } | ||
| std::cout << std::endl; | ||
| return 0; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| #ifndef PRODUCT_EXCEPT_SELF_MAIN_MAIN_H_ // The format of the symbol name should be <PROJECT>_<PATH>_<FILE>_H_. | ||
| #define PRODUCT_EXCEPT_SELF_MAIN_MAIN_H_ | ||
|
|
||
| #include <vector> | ||
|
|
||
| class Solution { | ||
| public: | ||
| std::vector<int> productExceptSelf(std::vector<int>& nums); | ||
| }; | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| ## ステップ1 | ||
| O(n)で実装する必要があるためvectorを2回見ていく方法は使えない | ||
| 全てを掛け合わせた数字を出してから、nums[i]を割っていいく方法が思いついたが | ||
| 割り算も制約上使えない | ||
|
|
||
| 問題をもう一度読み直す | ||
| >The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer. | ||
| わざわざprefixとsuffixが記載があるということをヒントに | ||
| iの位置までの合計とiより後ろの合計を管理するvectorを二つ用意して | ||
|
|
||
| 最終的に掛け合わせると回答できそう | ||
| 時間計算量O(n) | ||
| 空間計算量O(n) | ||
|
|
||
| acceptまで30分 | ||
|
|
||
| ## ステップ2 | ||
| nums[i]を掛ける順序とタイミングを考えれば、 | ||
| iの位置までの合計とiより後ろの合計を管理するvectorを使う必要がなくなる。 | ||
|
|
||
| prefix_productとsuffix_productを使ってそれぞれ左側と右側の積を保持する。 | ||
| products_except_self[i]に掛けた後に、 | ||
| prefix_productとsuffix_productをnums[i]で更新することで、 | ||
| 各ステップではnums[i]を除いた積だけが使われるようになっている | ||
| =>いきなりこの解法に辿り着くのは難しそう | ||
|
|
||
| vector<int>の初期化について | ||
| https://stackoverflow.com/questions/42743604/default-values-when-creating-a-vector-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. 2次元行列作るときに使っていますね。 |
||
|
|
||
|
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> productExceptSelf(vector<int>& nums) {
int n = nums.size();
vector<int> prefix(n, 1);
partial_sum(nums.begin(), nums.end() - 1, prefix.begin() + 1, multiplies<int>());
vector<int> suffix(n, 1);
partial_sum(nums.rbegin(), nums.rend() - 1, suffix.rbegin() + 1, multiplies<int>());
vector<int> result(n);
transform(prefix.begin(), prefix.end(), suffix.begin(), result.begin(), multiplies<int>());
return result;
}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 |
||
| ## ステップ3 | ||
| **3回書き直しやりましょう、といっているのは、不自然なところや負荷の高いところは覚えられないからです。** | ||
|
|
||
| ## 他の方の解法 | ||
| prefixやsuffixを単体で使うよりprefix_〇〇というように何が入っているのかわかるような名前がいいと感じた | ||
| resやlengthに関しても何が入っているのか分かるような変数名をつけたい | ||
| https://github.com/t-ooka/leetcode/pull/5 | ||
|
|
||
| indexの管理方法を考えることで左側の積と右側の積を一度に計算することができる | ||
|
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. できますが、私はそんなに推奨しませんね。 |
||
| https://discord.com/channels/1084280443945353267/1200089668901937312/1200403156073455646 | ||
| ## Discorなど | ||
|
|
||
| # PRに対するコメント | ||
| partial_sumとtransformを使っても解答可能 | ||
| =>いずれの関数も知らなかったので普段使っている物以外にも足を伸ばす姿勢を意識。 | ||
|
|
||
| partial_sum | ||
| https://cpprefjp.github.io/reference/numeric/partial_sum.html | ||
| https://en.cppreference.com/w/cpp/algorithm/partial_sum | ||
|
|
||
| multiplies | ||
| https://cpprefjp.github.io/reference/functional/multiplies.html | ||
| https://en.cppreference.com/w/cpp/utility/functional/multiplies | ||
|
|
||
| transform | ||
| https://cpprefjp.github.io/reference/algorithm/transform.html | ||
| https://en.cppreference.com/w/cpp/algorithm/transform | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| class Solution { | ||
| public: | ||
| vector<int> productExceptSelf(vector<int>& nums) { | ||
| if (nums.size() == 0) { | ||
| return {}; | ||
| } | ||
| vector<int> prefix_products(nums.size()); | ||
| // デフォルトの初期化は0だが、 | ||
| // indexが0の場所の計算に影響を与えないように1で初期化する | ||
| prefix_products[0] = 1; | ||
| for (int i = 1; i < nums.size(); i++) { | ||
| prefix_products[i] = prefix_products[i - 1] * nums[i - 1]; | ||
| } | ||
|
|
||
| vector<int> suffix_products(nums.size()); | ||
| suffix_products[nums.size() - 1] = 1; | ||
| for (int i = nums.size() - 2; i >= 0; i--) { | ||
| suffix_products[i] = suffix_products[i + 1] * nums[i + 1]; | ||
| } | ||
|
|
||
| vector<int> products_except_self(nums.size()); | ||
| for (int i = 0; i < nums.size(); i++) { | ||
| products_except_self[i] = prefix_products[i] * suffix_products[i]; | ||
| } | ||
| return products_except_self; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| class Solution { | ||
| public: | ||
| vector<int> productExceptSelf(vector<int>& nums) { | ||
| if (nums.size() == 0) { | ||
| return {}; | ||
| } | ||
|
|
||
| // デフォルトは0で初期化されるので1で初期化しておく | ||
| vector<int> products_except_self(nums.size(), 1); | ||
| int prefix_product = 1; | ||
| for (int i = 0; i < nums.size(); i++) { | ||
| products_except_self[i] *= prefix_product; | ||
| prefix_product *= nums[i]; | ||
| } | ||
|
|
||
| int suffix_product = 1; | ||
| for (int i = nums.size() - 1; i >= 0; i--) { | ||
| products_except_self[i] *= suffix_product; | ||
| suffix_product *= nums[i]; | ||
| } | ||
|
|
||
| return products_except_self; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| class Solution { | ||
| public: | ||
| vector<int> productExceptSelf(vector<int>& nums) { | ||
| if (nums.size() == 0) { | ||
| return {}; | ||
| } | ||
|
|
||
| vector<int> products_except_self(nums.size(), 1); | ||
| int prefix_product = 1; | ||
| for (int i = 0; i < nums.size(); i++) { | ||
| products_except_self[i] *= prefix_product; | ||
| prefix_product *= nums[i]; | ||
| } | ||
|
|
||
| int suffix_product = 1; | ||
| for (int i = nums.size() - 1; i >= 0; i--) { | ||
| products_except_self[i] *= suffix_product; | ||
| suffix_product *= nums[i]; | ||
| } | ||
|
|
||
| return products_except_self; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| class Solution { | ||
| public: | ||
| vector<int> productExceptSelf(vector<int>& nums) { | ||
| if (nums.empty()) { | ||
| return {}; | ||
| } | ||
|
|
||
| int num_size = nums.size(); | ||
|
|
||
| vector<int> prefix_products(num_size, 1); | ||
| partial_sum(nums.begin(), nums.end() - 1, prefix_products.begin() + 1, multiplies<int>()); | ||
|
|
||
| vector<int> suffix_products(num_size, 1); | ||
| partial_sum(nums.rbegin(), nums.rend() - 1, suffix_products.rbegin() + 1, multiplies<int>()); | ||
|
|
||
| vector<int> products_except_self(num_size); | ||
| transform(prefix_products.begin(), prefix_products.end(), suffix_products.begin(), | ||
| products_except_self.begin(), multiplies<int>()); | ||
| return products_except_self; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| class Solution { | ||
| public: | ||
| vector<int> productExceptSelf(vector<int>& nums) { | ||
| if (nums.empty()) { | ||
| return {}; | ||
| } | ||
|
|
||
| vector<int> products_except_self(nums.size(), 1); | ||
| int prefix_product = 1; | ||
| for (int i = 0; i < nums.size(); i++) { | ||
| products_except_self[i] *= prefix_product; | ||
| prefix_product *= nums[i]; | ||
| } | ||
|
|
||
| int suffix_product = 1; | ||
| for (int i = nums.size() - 1; i >= 0; i--) { | ||
| products_except_self[i] *= suffix_product; | ||
| suffix_product *= nums[i]; | ||
| } | ||
|
|
||
| return products_except_self; | ||
| } | ||
| }; |
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.empty() のほうがシンプルだと思います。
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.
@nodchip
レビューありがとうございます。確かにこちらの方が素直ですね。step4_2に追加しました。またこちらのもので3回書ける練習をしました。