From 9559ed2505ab08bb139d7d5337dc70e4e559d5e6 Mon Sep 17 00:00:00 2001 From: mike <59136831+Mike0121@users.noreply.github.com> Date: Sun, 23 Jun 2024 18:04:29 +0900 Subject: [PATCH] Create 560. Subarray Sum Equals K.md https://leetcode.com/problems/subarray-sum-equals-k/description/ --- .../560. Subarray Sum Equals K.md" | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 "\347\253\266\346\212\200\343\203\227\343\203\255\345\260\261\346\264\273\351\203\250PR\347\224\250/560. Subarray Sum Equals K.md" diff --git "a/\347\253\266\346\212\200\343\203\227\343\203\255\345\260\261\346\264\273\351\203\250PR\347\224\250/560. Subarray Sum Equals K.md" "b/\347\253\266\346\212\200\343\203\227\343\203\255\345\260\261\346\264\273\351\203\250PR\347\224\250/560. Subarray Sum Equals K.md" new file mode 100644 index 0000000..7fc41db --- /dev/null +++ "b/\347\253\266\346\212\200\343\203\227\343\203\255\345\260\261\346\264\273\351\203\250PR\347\224\250/560. Subarray Sum Equals K.md" @@ -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)
+空間計算量: O(1)
+> はじめに思いついた解法として、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)
+空間計算量: O(1)
+> 次に最適解が思いつかなかったため、二重ループで解いたが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)
+空間計算量: O(N)
+> 以前の自身の解法をもとに、累積和を使って解いた。 +```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回目と同じ
+空間計算量:1回目と同じ
+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回目と同じ
+空間計算量:1回目と同じ
+2回目と同じ。 +```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 +``` +