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
32 changes: 32 additions & 0 deletions 209.MinimumSizeSubarraySum/cumulative_sum.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
vector<int> cumulative_sum(nums.size() + 1);
cumulative_sum[0] = 0;
for (int i = 0; i < nums.size(); i++) {
Copy link

Choose a reason for hiding this comment

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

std::partial_sum() も使えると思います。

vector<int> cumulative_sum(1);
std::partial_sum(nums.begin(), nums.end(), std::back_inserter(cumulative_sum));

読みやすいかは微妙なところだと思います。

cumulative_sum[i + 1] = cumulative_sum[i] + nums[i];
}

int min_length = NOANSWER;
int left = 0;
int right = 1;
while (right < cumulative_sum.size()) {
while (left < right) {
if (cumulative_sum[right] - cumulative_sum[left] < target) {
break;
}
min_length = min(min_length, right - left);
left++;
}
right++;
}

if (min_length == NOANSWER) {
return 0;
}
return min_length;
}

private:
static constexpr int NOANSWER = numeric_limits<int>::max();
};
40 changes: 40 additions & 0 deletions 209.MinimumSizeSubarraySum/memo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
## ステップ1
一度解いたことがあり解き方を覚えていた。
左側のインデックスをleft、右側のインデックスをrightとする。
変数sumにleftからright区間の合計値を持たせておいて、
sumがtargetを超える場合はleftを進める。target以下の間はrightを進める。

## ステップ2
左側をループで回す方法がありstep2_2で実装。
右側をループで回す方が直感的な気がする。

累積和で解くことも可能、cumulative_sum.cppで実装
>nums は役割を全うして prefix_sum が代わりに進む準備ができた
>prefix_sum の left, right を使って考える
自分のこの考え方がしっくりきました
https://github.com/Yoshiki-Iwasa/Arai60/pull/43/commits/4423fb7f61bb4507ed7846c0964b0832b5d387de

累積和を作る際にprefixSums[i] = prefixSums[i - 1] + nums[i - 1];を使っている。
ここは好みの問題か
https://github.com/goto-untrapped/Arai60/pull/40

## ステップ3
**3回書き直しやりましょう、といっているのは、不自然なところや負荷の高いところは覚えられないからです。**

## 他の方の解法
leetcodeの解答例でsum += nums[r++];というふうにインクリメントしながらsumに追加する方法があった。
1行に2つの処理を纏めるより分けた方が好み。

Choose a reason for hiding this comment

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

私も分けた方が分かりやすいなと思いました。


Pythonのmath.infは型がfloat。言語が変わるとこの辺りの仕様は理解しておかないとバグに繋がりそう。
右側をループで回す方法で解いたが、左側を回す方法もあり。
余談、cumulative sumを略してcum sumというの知らなかった。。。

Choose a reason for hiding this comment

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

numpyにもcumsumメソッドがあります。
https://numpy.org/doc/2.2/reference/generated/numpy.cumsum.html

ただ、そんなに一般的ではない、という反応を見た記憶もあります。

Copy link
Owner Author

Choose a reason for hiding this comment

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

ありがとうございます!

https://github.com/fhiyo/leetcode/pull/49

numsに負の値が入ってきたときを考える
→自分のコードだと動かない
sum -= nums[left];の際に意図しない挙動になる。
https://github.com/goto-untrapped/Arai60/pull/40
https://github.com/Mike0121/LeetCode/pull/22

## Discorなど

27 changes: 27 additions & 0 deletions 209.MinimumSizeSubarraySum/step1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int min_length = NOANSWER;
int sum = 0;

int left = 0;
for (int right = 0; right < nums.size(); right++) {
sum += nums[right];
while (sum >= target) {
min_length = min(min_length, right - left + 1);
sum -= nums[left];
left++;
}
}

if (min_length != NOANSWER) {
return min_length;
} else {
return 0;
}
}

private:
static constexpr int NOANSWER = numeric_limits<int>::max();
Copy link

Choose a reason for hiding this comment

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

個人的には、これ定数で置かないほうが、上から読んでいって自然に理解できると思いますが、わりと趣味の範囲かなとは思います。

Copy link
Owner Author

Choose a reason for hiding this comment

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

@oda
一つ覚えでやってしまってますね。。。
ありがとうございます。

};

27 changes: 27 additions & 0 deletions 209.MinimumSizeSubarraySum/step2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int min_length = NOANSWER;

int sum = 0;
int left = 0;
for (int right = 0; right < nums.size(); right++) {
sum += nums[right];

while (sum >= target) {
min_length = min(min_length, right - left + 1);
sum -= nums[left];
left++;
}
}

if (min_length == NOANSWER) {
return 0;
}
return min_length;
}

private:
static constexpr int NOANSWER = numeric_limits<int>::max();
};

30 changes: 30 additions & 0 deletions 209.MinimumSizeSubarraySum/step2_2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int min_length = NOANSWER;
int sum = 0;

int right = 0;
for (int left = 0; left < nums.size(); left++) {
while (right < nums.size() && sum < target) {
sum += nums[right];
right++;
}
if (sum < target) {
break;
}
min_length = min(min_length, right - left);
sum -= nums[left];
}

if (min_length != NOANSWER) {
return min_length;
} else {
return 0;
}
}

private:
static constexpr int NOANSWER = numeric_limits<int>::max();
};

26 changes: 26 additions & 0 deletions 209.MinimumSizeSubarraySum/step3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int min_length = NOANSWER;
int sum = 0;

int left = 0;
for (int right = 0; right < nums.size(); right++) {
sum += nums[right];
while (sum >= target) {
min_length = min(min_length, right - left + 1);
sum -= nums[left];
left++;
}
}

if (min_length == NOANSWER) {
return 0;
}
return min_length;
}

private:
static constexpr int NOANSWER = numeric_limits<int>::max();
};