-
Notifications
You must be signed in to change notification settings - Fork 0
Create 560. Subarray Sum Equals K.md #33
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,142 @@ | ||
累積和に関する議論 | ||
``` | ||
累積和を日常で見る機会ってあると思うんですよ。 | ||
たとえばですけれども、電車の各駅の距離とかかる時間が書かれていて、ちょうど10分かかる駅の組み合わせはどれか、といわれたら、 | ||
(これはマイナスが出ないので更に楽ですが、)終着駅から出発する電車が、どこを何時何分に通過するかを書き出しながら、 | ||
その10分前に別の駅にいたかを確認したらいいですよね。 | ||
|
||
マイナスが出るようにするために、標高差とかにします? つまり、各駅間の標高差が書かれていて、ちょうど標高差が 100 m な駅の組み合わせを知りたい。 | ||
問題は、駅の組み合わせの数ですが、とりあえず、駅の組み合わせを全部列挙してみましょうか。そうすると、multimap でも使いますか。 | ||
|
||
駅A → 駅B: 5分 | ||
駅B → 駅C: 3分 | ||
駅C → 駅D: 2分 | ||
駅D → 駅E: 1分 | ||
駅E → 駅F: 4分 | ||
|
||
累積和: [0, 5, 8, 10, 11, 15] ([A->A, A->B, A->C, A->D, A->E, A->F]) | ||
この場合、10と0があるので、駅Aから駅Dまでで10分、 | ||
この場合、15と5があるので、駅Bから駅Fまでで10分 | ||
``` | ||
|
||
``` | ||
i番目までの累積和とj番目までの累積和が等しい場合その間[i, j)の要素の和は0となる。 | ||
prefixsum[i] = prefixsum[j] (i < j)の時、 | ||
prefixsum[i] = nums[0] + nums[1] + nums[2] + nums[3]... + nums[i - 1] | ||
prefixsum[j] = nums[0] + nums[1] + nums[2] + nums[3]... + nums[i - 1] **+ nums[i] ... + nums[j - 1]** | ||
許通部分を引き算して、 | ||
nums[i] + nums[i + 1] + num[i + 2] ... + nums[j - 1] = 0 | ||
``` | ||
|
||
## two-pointersによる解法 (×) | ||
### 0回目 v1 | ||
時間計算量: O(N^2)<br> | ||
空間計算量: O(1)<br> | ||
> はじめに思いついた解法として、slidingwindowの様に、値がtarget以上になった場合、 | ||
> windowを狭めていく解法を思いついた。Description上のテストケースは通過したが、 | ||
> numsの値にnegativeが入るとエラーが出ることを考慮しておらず大反省。 | ||
|
||
|
||
```python | ||
class Solution: | ||
def subarraySum(self, nums: List[int], k: int) -> int: | ||
count = 0 | ||
prefix_sum = 0 | ||
left = 0 | ||
for num in nums: | ||
prefix_sum += num | ||
|
||
while prefix_sum >= k: | ||
if prefix_sum == k: | ||
count += 1 | ||
prefix_sum -= nums[left] | ||
left += 1 | ||
return count | ||
``` | ||
|
||
|
||
## 二重ループによる解法 (TLE) | ||
### 0回目 v2 | ||
時間計算量: O(N^2)<br> | ||
空間計算量: O(1)<br> | ||
> 次に最適解が思いつかなかったため、二重ループで解いたがTLE。 | ||
|
||
```python | ||
class Solution: | ||
def subarraySum(self, nums: List[int], k: int) -> int: | ||
subarray_count = 0 | ||
for i in range(len(nums)): | ||
total = 0 | ||
for j in range(i, len(nums)): | ||
total += nums[j] | ||
if total == k: | ||
subarray_count += 1 | ||
|
||
return subarray_count | ||
``` | ||
|
||
## HashMapによる解法 | ||
### 1回目 | ||
時間計算量: O(N)<br> | ||
空間計算量: O(N)<br> | ||
> 以前の自身の解法をもとに、累積和を使って解いた。 | ||
```python | ||
class Solution: | ||
def subarraySum(self, nums: List[int], k: int) -> int: | ||
sum_to_count = defaultdict(int) | ||
sum_to_count[0] = 1 | ||
subarray_count = 0 | ||
prefix_sum = 0 | ||
|
||
for num in nums: | ||
prefix_sum += num | ||
if prefix_sum - k in sum_to_count: | ||
subarray_count += sum_to_count[prefix_sum - k] | ||
sum_to_count[prefix_sum] += 1 | ||
|
||
return subarray_count | ||
``` | ||
|
||
### 2回目 | ||
時間計算量:1回目と同じ <br> | ||
空間計算量:1回目と同じ <br> | ||
sum_to_countをprefix_sum_to_countに変更。 | ||
|
||
```python | ||
class Solution: | ||
def subarraySum(self, nums: List[int], k: int) -> int: | ||
prefix_sum = 0 | ||
prefix_sum_to_count = defaultdict(int) | ||
prefix_sum_to_count[0] = 1 | ||
subarray_count = 0 | ||
|
||
for num in nums: | ||
prefix_sum += num | ||
if prefix_sum - k in prefix_sum_to_count: | ||
subarray_count += prefix_sum_to_count[prefix_sum - k] | ||
prefix_sum_to_count[prefix_sum] += 1 | ||
|
||
return subarray_count | ||
``` | ||
|
||
### 3回目 | ||
時間計算量:1回目と同じ <br> | ||
空間計算量:1回目と同じ <br> | ||
2回目と同じ。 | ||
```python | ||
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. 細かいですが、 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. ありがとうございます、そこは考慮できていませんでした。できるだけ書く様にします。 |
||
class Solution: | ||
def subarraySum(self, nums: List[int], k: int) -> int: | ||
prefix_sum = 0 | ||
prefix_sum_to_count = defaultdict(int) | ||
prefix_sum_to_count[0] = 1 | ||
subarray_count = 0 | ||
|
||
for num in nums: | ||
prefix_sum += num | ||
if prefix_sum - k in prefix_sum_to_count: | ||
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. defaultdict を使っているので、この2行は単に(if 文は省略して) 追記:「この2行」とは if prefix_sum - k in prefix_sum_to_count:
subarray_count += prefix_sum_to_count[prefix_sum - k] のことです。github上だとどこを指しているのかわかりにくかったので追記しました🙏 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. @tshimosake さん、 @SuperHotDogCat さん |
||
subarray_count += prefix_sum_to_count[prefix_sum - k] | ||
prefix_sum_to_count[prefix_sum] += 1 | ||
|
||
return subarray_count | ||
``` | ||
|
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.
https://docs.python.org/3/library/collections.html#defaultdict-objects
https://docs.python.org/3.12/library/stdtypes.html#dict.get
.get(key, default=None) という手があります。