From dcd1de2bc48c23df9391b06edce84138e0902264 Mon Sep 17 00:00:00 2001 From: kazukiii Date: Fri, 21 Jun 2024 01:03:14 -0700 Subject: [PATCH 1/2] =?UTF-8?q?step1,=20step2,=20step3=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- arai60/subarray-sum-equals-k/README.md | 65 +++++++++++++++++++ arai60/subarray-sum-equals-k/step1.cpp | 17 +++++ .../step1_brute_force.cpp | 18 +++++ arai60/subarray-sum-equals-k/step2.cpp | 17 +++++ arai60/subarray-sum-equals-k/step3.cpp | 15 +++++ 5 files changed, 132 insertions(+) create mode 100644 arai60/subarray-sum-equals-k/README.md create mode 100644 arai60/subarray-sum-equals-k/step1.cpp create mode 100644 arai60/subarray-sum-equals-k/step1_brute_force.cpp create mode 100644 arai60/subarray-sum-equals-k/step2.cpp create mode 100644 arai60/subarray-sum-equals-k/step3.cpp diff --git a/arai60/subarray-sum-equals-k/README.md b/arai60/subarray-sum-equals-k/README.md new file mode 100644 index 0000000..9ae2b29 --- /dev/null +++ b/arai60/subarray-sum-equals-k/README.md @@ -0,0 +1,65 @@ +## 考察 +- 初見の問題 +- nums[i] >= 0 なら sliding window でやりたいところだが負の数もあり +- 区間和を高速で計算したいので累積和を使用 +- 方針 + - 累積和 + 区間全探索 + - time: O(n^2), space: O(n) + - nums.length <= 2 * 10^4 なので通りそうだが最適解ではなさそう + - 通った -> `step1_brute_force.cpp` +- もう少し最適化を考えたい +- 方針2 + - 引き算だけど、two sumの要領でいけるはず + - あるインデックスより前の累積和の度数分布のようなものを追加メモリで持ちたい + - time: O(n), space: O(n^2) +- MLE +```cpp +class Solution { +public: + int subarraySum(vector& nums, int k) { + int n = nums.size(); + vector prefix_sum(n + 1, 0); + vector> prefix_sum_count(n + 1, {{0, 1}}); + for (int i = 0; i < n; i++) { + prefix_sum[i + 1] = prefix_sum[i] + nums[i]; + prefix_sum_count[i + 1] = prefix_sum_count[i]; + prefix_sum_count[i + 1][prefix_sum[i + 1]]++; + } + + int answer = 0; + for (int i = 1; i <= n; i++) { + int difference = prefix_sum[i] - k; + answer += prefix_sum_count[i - 1][difference]; + } + return answer; + } +}; +``` +- もう少し考える +- 方針3 + - i -> i + 1 への遷移しかないので、in-place DPの要領で次元を一つ消せそう + - 通った。難しかった。 + - time: O(n), space: O(n) + +## Step2 +- Solutionsを覗いてみた + - 方針はだいたい良さそう +- 変数名を見直し + - answer -> total + - prefix_sum_count -> prefix_sum_to_count +- 他の人のPRを検索 + - numpyにはcumsumがある + - https://github.com/TORUS0818/leetcode/pull/18#discussion_r1646398612 + - inclusiveな範囲を表現する際には、変数名はfirst-lastが良い + - https://github.com/goto-untrapped/Arai60/pull/28#discussion_r1642960547 + - 累積和についての小田さんのメモ + - https://github.com/Exzrgs/LeetCode/pull/25#discussion_r1640727899 + - https://discord.com/channels/1084280443945353267/1183683738635346001/1192145962479665304 + - 類題 + - https://github.com/SuperHotDogCat/coding-interview/pull/29#issuecomment-2169284348 + - https://leetcode.com/problems/subarray-sums-divisible-by-k/description/ + +## Step3 +- 1回目: 1m38s +- 2回目: 1m30s +- 3回目: 1m29s diff --git a/arai60/subarray-sum-equals-k/step1.cpp b/arai60/subarray-sum-equals-k/step1.cpp new file mode 100644 index 0000000..454ebbc --- /dev/null +++ b/arai60/subarray-sum-equals-k/step1.cpp @@ -0,0 +1,17 @@ +class Solution { +public: + int subarraySum(vector& nums, int k) { + int n = nums.size(); + int prefix_sum = 0; + unordered_map prefix_sum_count = {{0, 1}}; + + int answer = 0; + for (int i = 0; i < n; i++) { + prefix_sum += nums[i]; + int difference = prefix_sum - k; + answer += prefix_sum_count[difference]; + prefix_sum_count[prefix_sum]++; + } + return answer; + } +}; diff --git a/arai60/subarray-sum-equals-k/step1_brute_force.cpp b/arai60/subarray-sum-equals-k/step1_brute_force.cpp new file mode 100644 index 0000000..b89c086 --- /dev/null +++ b/arai60/subarray-sum-equals-k/step1_brute_force.cpp @@ -0,0 +1,18 @@ +class Solution { +public: + int subarraySum(vector& nums, int k) { + int n = nums.size(); + int answer = 0; + vector prefix_sum(n + 1, 0); + for (int i = 0; i < n; i++) { + prefix_sum[i + 1] = prefix_sum[i] + nums[i]; + } + + for (int i = 0; i < n; i++) { + for (int j = i + 1; j <= n; j++) { + if (prefix_sum[j] - prefix_sum[i] == k) answer++; + } + } + return answer; + } +}; diff --git a/arai60/subarray-sum-equals-k/step2.cpp b/arai60/subarray-sum-equals-k/step2.cpp new file mode 100644 index 0000000..45da402 --- /dev/null +++ b/arai60/subarray-sum-equals-k/step2.cpp @@ -0,0 +1,17 @@ +class Solution { +public: + int subarraySum(vector& nums, int k) { + int n = nums.size(); + int prefix_sum = 0; + unordered_map prefix_sum_to_count = {{0, 1}}; + + int total = 0; + for (int i = 0; i < n; i++) { + prefix_sum += nums[i]; + int difference = prefix_sum - k; + total += prefix_sum_to_count[difference]; + prefix_sum_to_count[prefix_sum]++; + } + return total; + } +}; diff --git a/arai60/subarray-sum-equals-k/step3.cpp b/arai60/subarray-sum-equals-k/step3.cpp new file mode 100644 index 0000000..b10a48d --- /dev/null +++ b/arai60/subarray-sum-equals-k/step3.cpp @@ -0,0 +1,15 @@ +class Solution { +public: + int subarraySum(vector& nums, int k) { + int prefix_sum = 0; + unordered_map prefix_sum_to_count = {{0, 1}}; + int total = 0; + for (int i = 0; i < nums.size(); i++) { + prefix_sum += nums[i]; + int difference = prefix_sum - k; + total += prefix_sum_to_count[difference]; + prefix_sum_to_count[prefix_sum]++; + } + return total; + } +}; From 0064bbbcea30a2980aa84f40bfb951c2c41fdef6 Mon Sep 17 00:00:00 2001 From: kazukiii Date: Fri, 21 Jun 2024 16:09:14 -0700 Subject: [PATCH 2/2] =?UTF-8?q?step4=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- arai60/subarray-sum-equals-k/README.md | 4 ++++ .../step4_subarray-sums-divisible-by-k.cpp | 15 +++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 arai60/subarray-sum-equals-k/step4_subarray-sums-divisible-by-k.cpp diff --git a/arai60/subarray-sum-equals-k/README.md b/arai60/subarray-sum-equals-k/README.md index 9ae2b29..36f38e8 100644 --- a/arai60/subarray-sum-equals-k/README.md +++ b/arai60/subarray-sum-equals-k/README.md @@ -63,3 +63,7 @@ public: - 1回目: 1m38s - 2回目: 1m30s - 3回目: 1m29s + +## Step4 +- 上の類題を解く + - `step4_subarray-sums-divisible-by-k.cpp` diff --git a/arai60/subarray-sum-equals-k/step4_subarray-sums-divisible-by-k.cpp b/arai60/subarray-sum-equals-k/step4_subarray-sums-divisible-by-k.cpp new file mode 100644 index 0000000..d4b3c87 --- /dev/null +++ b/arai60/subarray-sum-equals-k/step4_subarray-sums-divisible-by-k.cpp @@ -0,0 +1,15 @@ +class Solution { +public: + int subarraysDivByK(vector& nums, int k) { + int prefix_sum = 0; + unordered_map prefix_sum_count_mod_k = {{0, 1}}; + int answer = 0; + for (int i = 0; i < nums.size(); i++) { + prefix_sum += nums[i]; + int needed = (prefix_sum % k + k) % k; + answer += prefix_sum_count_mod_k[needed]; + prefix_sum_count_mod_k[needed]++; + } + return answer; + } +};