Subarray Sum Equals K medium
Problem Statement
Given an array of integers nums
and an integer k
, return the total number of continuous subarrays whose sum equals to k
.
Example 1:
Input: nums = [1,1,1], k = 2 Output: 2
Example 2:
Input: nums = [1,2,3], k = 3 Output: 2
Steps
-
Prefix Sum: We'll use a prefix sum approach. A prefix sum at index
i
is the sum of all elements from index 0 toi
. We can efficiently calculate these sums. -
Hash Map: We'll use a hash map (unordered_map in C++) to store the frequency of each prefix sum encountered so far. The key will be the prefix sum, and the value will be its count.
-
Iteration: We iterate through the
nums
array. For each element:- Calculate the current prefix sum.
- Check if
prefixSum - k
exists as a key in the hash map. If it does, it means there's a subarray ending at the current index with a sum ofk
. We add its count to our result. - Update the frequency of the current
prefixSum
in the hash map.
-
Handle k=0: If k is 0, we must handle the case where a subarray with sum 0 exists separately since
prefixSum -k
would lead to division by zero.
Explanation
The core idea is that if the prefix sum at index i
is prefixSum_i
and the prefix sum at index j
(where j < i
) is prefixSum_j
, then the sum of the subarray from index j+1
to i
is prefixSum_i - prefixSum_j
. If we want this sum to be equal to k
, then prefixSum_i - prefixSum_j = k
, which means prefixSum_i - k = prefixSum_j
. Therefore, we check if prefixSum_i - k
exists in our hash map. The number of times it exists represents the number of subarrays ending at index i
with a sum of k
.
Code
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
int subarraySum(vector<int>& nums, int k) {
unordered_map<long long, int> prefixSumCount; //Using long long to avoid overflow
prefixSumCount[0] = 1; //Important: Initialize for subarrays starting at index 0
long long prefixSum = 0;
int count = 0;
for (int num : nums) {
prefixSum += num;
if (prefixSumCount.count(prefixSum - k)) {
count += prefixSumCount[prefixSum - k];
}
prefixSumCount[prefixSum]++;
}
return count;
}
int main() {
vector<int> nums1 = {1, 1, 1};
int k1 = 2;
cout << "Example 1: " << subarraySum(nums1, k1) << endl; // Output: 2
vector<int> nums2 = {1, 2, 3};
int k2 = 3;
cout << "Example 2: " << subarraySum(nums2, k2) << endl; // Output: 2
vector<int> nums3 = {-1,-1,1};
int k3 = 0;
cout << "Example 3: " << subarraySum(nums3, k3) << endl; // Output: 1
return 0;
}
Complexity
- Time Complexity: O(n), where n is the length of the
nums
array. We iterate through the array once. Hash map operations (insertion and lookup) are on average O(1). - Space Complexity: O(n) in the worst case, as the hash map could store up to n different prefix sums. In the best case it could be O(1) (if there are very few unique prefix sums).