Skip to content
Open
Show file tree
Hide file tree
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
17 changes: 17 additions & 0 deletions 152.MaximumProductSubarray/brute_force.cpp
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;
}
};
36 changes: 36 additions & 0 deletions 152.MaximumProductSubarray/memo.md
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で実装)
Copy link

Choose a reason for hiding this comment

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

step 2 が私は愚直で気に入りました。このあたりで解いている人たちがいます。
https://discord.com/channels/1084280443945353267/1196498607977799853/1358736384604766238

Copy link
Owner Author

Choose a reason for hiding this comment

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

ありがとうございます。
小田さんの解法はstep2_2に近いので理解できました。
野田さんの解法は他のコメント、解説を読んでギリギリ理解できたような感覚です。きちんと言語化できないですが負の数が奇数になる場合を両サイドから見ていくことで避けていると理解しました。

これは初見で思いつくことが難しそうなので愚直に比較したい
https://leetcode.com/problems/maximum-product-subarray/solutions/48230/possibly-simplest-solution-with-o-n-time-complexity/

## Discorなど

19 changes: 19 additions & 0 deletions 152.MaximumProductSubarray/step1.cpp
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]));
Copy link

Choose a reason for hiding this comment

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

Python のようにしたければ

tie(a, b) = make_pair(b, a);

というのが一応ありますが、素直に両方の変数を new_max, new_min とでも一度置いてから更新のほうが読みやすいでしょう。

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;
}
};
21 changes: 21 additions & 0 deletions 152.MaximumProductSubarray/step2.cpp
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;
}
};
21 changes: 21 additions & 0 deletions 152.MaximumProductSubarray/step2_2.cpp
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;
}
};

Choose a reason for hiding this comment

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

スクリーンショット 2025-07-30 5 18 35 discord内で見つけた他の方のコメントです。 https://discord.com/channels/1084280443945353267/1196498607977799853/1240265127207632896

参考記事:https://qiita.com/raiga0310/items/8a0df87ecb3e0b0c676a

Copy link
Owner Author

Choose a reason for hiding this comment

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

@Apo-Matchbox
確認有り難とうございます。漏れておりました。。。

21 changes: 21 additions & 0 deletions 152.MaximumProductSubarray/step3.cpp
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;
}
};