Skip to content
Open
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
90 changes: 90 additions & 0 deletions Python3/560. Subarray Sum Equals K.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
## Step 1. Initial Solution

- 連続する配列の一部の和がある値となるような配列の切り取り方の総数
- 二重ループで和が一致した時にcountしていく方法を最初に思い付いたがTLE
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

fuga-98/arai60#45 (comment)
こちらのコメントを参照されることをお勧めします。


```python
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
count = 0
cumulative_sums: List[int] = nums
for i in range(1, len(nums)):
cumulative_sums[i] += cumulative_sums[i-1]
target = k
for i in range(len(nums)):
for sum_to_index in cumulative_sums[i:]:
if target == sum_to_index:
count += 1
target = cumulative_sums[i] + k
return count
```

- 累積和を取っていっても結局探すところで線形時間だと上手くいかない
- 探す対象がHashMapじゃないといけない?
- 考えてみるも答えが分からない
- 答えを見てみると探すところは
- 前の累積和から探す
- 累積和はCountをHashMapに入れておく

という方針で実装できる


```python
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
count = 0
cumulative_sum = 0
cumulative_sum_to_count: Dict[int, int] = defaultdict(int)

for i in range(len(nums)):
cumulative_sum += nums[i]
if cumulative_sum == k:
count += 1
count += cumulative_sum_to_count[cumulative_sum - k]
cumulative_sum_to_count[cumulative_sum] += 1
return count
```

- `if cumulative_sum == k:` の代わりにHashMapに0: 1を入れておく方法もあるが、自然言語的には今の方が違和感なく出来ている気がするのでこのままにする
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

駅の標高差の話だと思うと、代入でもすんなりくるかもしれません。
https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0#heading=h.bp0g0ai41eln

あと、なんとなく考え方の章あたりを見ておいてもらえると嬉しいです。

- パフォーマンス最適化する目的なら変えるべき
- 今回はかなり悩んでしまう時間が長かったので、うだうだ悩む癖をやめたい
- 思考整理→実装のステップで思考整理から詰まっている場合は諦めた方が良い
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

こちら参考になるかもしれません
plushn/SWE-Arai60#15 (comment)


### Complexity Analysis

- 時間計算量:O(n)
- 空間計算量:O(n)

## Step 2. Alternatives

- accumulateなる関数がある
- https://docs.python.org/ja/3.13/library/itertools.html#itertools.accumulate
- 他にもitertoolsは知らないものが多そう
- 変数名についてprefix_sumとしている人がいるがよく知らないので調べてみる

> In [computer science](https://en.wikipedia.org/wiki/Computer_science), the **prefix sum**, **cumulative sum**, **inclusive scan**, or simply **scan** of a sequence of numbers *x*0, *x*1, *x*2, ... is a second sequence of numbers *y*0, *y*1, *y*2, ..., the [sums](https://en.wikipedia.org/wiki/Summation) of [prefixes](https://en.wikipedia.org/wiki/Prefix_(computer_science)) ([running totals](https://en.wikipedia.org/wiki/Running_total)) of the input sequence
>
- defaultdictの第二引数で初期化できる
- 自分の初めの考え方に近いものでも
- 前の累積和から探す→×
- 累積和はCountをHashMapに入れておく→◯

ならO(n)で実行できる

- https://github.com/fuga-98/arai60/pull/17/files
- 結果に求められているのがCountなので、途中で使うデータ構造もCountのHashMapにする可能性を考えないといけない

## Step 3. Final Solution

```python
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
count = 0
prefix_sum_to_count: Dict[int, int] = defaultdict(int)
for prefix_sum in accumulate(nums):
if prefix_sum == k:
count += 1
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

私は、prefix_sum_to_count[0] = 1としたほうがわかりやすいと思いましたが、趣味ですかね。

count += prefix_sum_to_count[prefix_sum - k]
prefix_sum_to_count[prefix_sum] += 1
return count
```