Problem Statement
Given an array a[], find the number of subarrays in it, which have a sum of k.
Subarray: A subarray of an array is formed by deleting some(possibly zero) elements from the beginning or end of the array.
The red region shows a subarray of the original array.
Sample Test Cases
Input 1: a = [10, 2, -2, -20, 10], k = -10
Output 1: 3
Explanation 1: The subarrays are listed as below (1 – Based Indexing):
- [4, 5]
- [1, 4]
- [2, 5]
Input 2: a = [1, 1, 1], k = 2
Output 2: 2
Explanation 2: All subarrays of length 2 are valid subarrays in this case, and there are a total of 2 such subarrays.
Naive Approach
The naive approach is to generate all the subarrays of the array and calculate their sum. Whenever we find a subarray with a sum equal to k, we increment our counter by 1. Finally, we return the count which keeps track of the number of subarrays with a sum equal to k.
Since there are a total of (n * (n + 1)) / 2 subarrays of an array, and each subarray will take O(n) time to traverse and calculate their sum, the required time complexity of this approach will be cubic in nature.
C++ Code
int countSubarraysWithSumK(vector < int > & a, int K) { int n = a.size(); int count = 0; for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { int sum = 0; for (int k = i; k <= j; k++) { sum += a[k]; } count += (sum == K); } } return count; }
Java Code
public static int countSubarraysWithSumK(int[] a, int K) { int n = a.length; int count = 0; for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { int sum = 0; for (int k = i; k <= j; k++) { sum += a[k]; } count += (sum == K ? 1 : 0); } } return count; }
Python Code
def countSubarrayswithSumK(a, K): n = len(a) count = 0 for i in range(n): for j in range(i, n): sum = 0 for k in range(i, j + 1): sum += a[k] count += sum == K return count
Complexity Analysis
- Time Complexity: O(n3)
- Space Complexity: O(1)
Optimal Approach
We can solve this problem in linear time complexity using a hashmap-based approach. The algorithm is described as follows:
- Traverse the array, and keep track of the current running sum up to the ith index in a variable, say sum.
- Also, hash the different values of the sum obtained so far, into a hashmap.
- If the sum equals k at any point in the array, increment the count of subarrays by 1.
- If this value of sum has exceeded k by a value of sum – k, we can find the number of subarrays, found so far with sum = sum – k, from our hashmap. Observe that if these subarrays are deleted from our current array, we will again obtain a sum of k. So, we add to our answer, the number of subarrays with sum = sum – k found so far from our hashmap.
- After traversing through the entire array once and applying the above steps, return the calculated result.
C++ Implementation
int countSubarraysWithSumK(vector < int > & a, int K) { int n = a.size(); unordered_map < int, int > hash; int count = 0, sum = 0; for (int i = 0; i < n; i++) { sum += a[i]; if (sum == K) { count++; } if (hash.find(sum - K) != hash.end()) { count += hash[sum - K]; } hash[sum]++; } return count; }
Java Implementation
public static int countSubarraysWithSumK(int[] a, int K) { int n = a.length; HashMap < Integer, Integer > hash = new HashMap < > (); int count = 0, sum = 0; for (int i = 0; i < n; i++) { sum += a[i]; if (sum == K) { count++; } if (hash.get(sum - K) != null) { count += hash.get(sum - K); } if (hash.get(sum) != null) { hash.put(sum, hash.get(sum) + 1); } else { hash.put(sum, 1); } } return count; }
Python Implementation
from collections import defaultdict def countSubarrayswithSumK(a, K): n = len(a) hash = defaultdict(lambda: 0) count = 0 sum = 0 for i in range(n): sum += a[i] if sum == K: count += 1 if (sum - K) in hash: count += hash[sum - K] hash[sum] += 1 return count
Complexity Analysis
- Time Complexity: O(n)
- Space Complexity: O(1)
Practice Problem
FAQs
Q. What is the time complexity of lookup in a hashmap?
A. The time complexity of lookup in a hashmap is O(1) amortized.
Q. Why is the number of subarrays of an array given by (n * (n + 1)) / 2?
A. The number of subarrays of an array can be calculated as there are,
- 1 subarray of length n
- 2 subarrays of length n – 1
- ……
- n subarrays of length 1
So, the total number of subarrays count out to a total of 1 + 2 + 3 + … n = (n * (n + 1)) / 2.