diff --git a/560. Subarray Sum Equals K.md b/560. Subarray Sum Equals K.md new file mode 100644 index 0000000..35b6a49 --- /dev/null +++ b/560. Subarray Sum Equals K.md @@ -0,0 +1,111 @@ +URL: https://leetcode.com/problems/subarray-sum-equals-k/ + +# Step 1 + +- 実装時間: 20分 +- 時間計算量: O(n**2) +- 空間計算量: O(n) + +```python +class Solution: + def subarraySum(self, nums: List[int], k: int) -> int: + accumulating_list = [0] + for num in nums: + accumulating_list.append(accumulating_list[-1] + num) + + result = 0 + for i in range(len(accumulating_list)): + for j in range(i + 1, len(accumulating_list)): + if accumulating_list[j] - accumulating_list[i] == k: + result += 1 + return result +``` + +2重ループではTLEしたのでO(n)で解決するように修正。 + +- 時間計算量: O(n) +- 空間計算量: O(n) + +```python +class Solution: + def subarraySum(self, nums: List[int], k: int) -> int: + accumulating_list = [0] + for num in nums: + accumulating_list.append(accumulating_list[-1] + num) + + result = 0 + num_to_previous_occurrence = defaultdict(int) + for num in accumulating_list: + complement_number = num - k + result += num_to_previous_occurrence[complement_number] + num_to_previous_occurrence[num] += 1 + return result +``` + +# Step 2 + +- 一度accumulating_listを作るのはムダだと気づいた。 + +- 参考にしたURL + - https://github.com/fhiyo/leetcode/pull/19 + - https://github.com/sakupan102/arai60-practice/pull/17 + - https://github.com/goto-untrapped/Arai60/pull/28 + - https://github.com/TORUS0818/leetcode/pull/18 + - https://github.com/kazukiii/leetcode/pull/17 + - https://github.com/Yoshiki-Iwasa/Arai60/pull/15 + - https://github.com/nittoco/leetcode/pull/22 + - https://github.com/seal-azarashi/leetcode/pull/16 + - https://github.com/hroc135/leetcode/pull/16 + - https://github.com/tarinaihitori/leetcode/pull/16 + +- > number_of_ は num_ と略すことが多いように思います。 subarray は複数ある場合がありますので、 subarrays と複数形にしたほうが良いと思います。 num_subarrays でいかがでしょうか? + - https://github.com/sakupan102/arai60-practice/pull/17#discussion_r1582005581 + +- > numpyで馴染みがあるので、個人的には累積和というとcumsumを想起します。色々見ていてprefix_sumがしっくりきているので、今後はこちらを使おうかと思っていますが。 + - https://github.com/TORUS0818/leetcode/pull/18/files#r1646733442 + - 僕も、prefix_sumを使おう。cumsumは聞いたことがなかったので覚えておく。 + - accumulativeを辞書引くと「1 ⦅かたく⦆ 〈数量・度合いなどが〉次第に増加する; 累積的な (!cumulativeの方が一般的) 」とあったので、どちらにしてもaccumulativeは避ける。 + - https://en.wikipedia.org/wiki/Prefix_sum + +- 人のコードをみた後に改めて自分のコードを見ると、変数名`occurrence`が明らかに異質に見える。 + - 変数名を決めた時の気持ちは「ここまでみてきた中で特定の数が発生した個数」と言いたかった。 + - 「XXの個数」という意味はcountという用語で統一した方がわかりやすそう? + - とくに今回は発生した個数を数えて行っているので、より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 + num_subarrays = 0 + for num in nums: + prefix_sum += num + num_subarrays += prefix_sum_to_count[prefix_sum - k] + prefix_sum_to_count[prefix_sum] += 1 + + return num_subarrays +``` + +# Step 3 + +- 時間計算量: O(n) +- 空間計算量: O(n) + +```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 + num_subarrays = 0 + for num in nums: + prefix_sum += num + num_subarrays += prefix_sum_to_count[prefix_sum - k] + prefix_sum_to_count[prefix_sum] += 1 + return num_subarrays +``` + +- 書いた後の感想。 + - 結構resultを使いたくなることがわかった。 + - コード補完を使ってないからめんどくさいという理由もあるし、関数の戻り値であるという感じを表現したくなる気がした。