Counting Subarrays with Sum Equal to K: A Prefix Sum Approach in Java
Finding subarrays with a specific sum is a classic problem in computer science. In this blog post, we'll explore an efficient solution using the concept of prefix sums and a HashMap in Java.
Understanding the Problem
Given an array of integers num and an integer k, we need to find the number of contiguous subarrays whose sum is equal to k.
The Prefix Sum Concept
The prefix sum of an array at index i is the sum of all elements from index 0 to i. Prefix sums allow us to quickly calculate the sum of any subarray in constant time.
The Algorithm
Our Java code utilizes the prefix sum concept along with a HashMap to efficiently count the subarrays with sum k:
Initialize Variables:
preSum: Stores the running prefix sum.hm: A HashMap to store prefix sums and their frequencies.cnt: Counts the number of subarrays with sumk.Initialize
hmwith(0, 1)because an empty subarray has a sum of 0.
Iterate Through the Array:
For each element
num[i]in the array:Update
preSumby addingnum[i].Calculate
remove = preSum - k. Ifhmcontainsremove, it means there's a prefix sum that, when subtracted from the currentpreSum, equalsk. This indicates a subarray with sumk.Increment
cntby the frequency ofremoveinhm.Update the frequency of the current
preSuminhm.
Return the Count:
- Return
cnt, which represents the number of subarrays with sumk.
- Return
Java Code Implementation
Java
package Arrays;
import java.util.HashMap;
import java.util.Map;
public class CountSubArraySumK {
public static int countSubArray(int num[], int k) {
int preSum = 0;
Map<Integer, Integer> hm = new HashMap<Integer, Integer>();
hm.put(0, 1);
int cnt = 0;
for (int i = 0; i < num.length; i++) {
preSum += num[i];
int remove = preSum - k;
if (hm.containsKey(remove)) {
cnt += hm.get(remove);
}
if (hm.containsKey(preSum)) {
hm.put(preSum, hm.get(preSum) + 1);
} else {
hm.put(preSum, 1);
}
}
return cnt;
}
public static void main(String[] args) {
int num[] = {3, 1, 2, 4, -4, -2};
System.out.println(countSubArray(num, 6));
int num2[] = {1, 1, 1};
System.out.println(countSubArray(num2, 2));
int num3[] = {1, 2, 3};
System.out.println(countSubArray(num3, 3));
int num4[] = {1, -1, 0};
System.out.println(countSubArray(num4, 0));
}
}
Step-by-Step Examples
Example 1: num = {3, 1, 2, 4, -4, -2}, k = 6
Initialization:
preSum = 0,hm = {0: 1},cnt = 0
Iteration:
i = 0,num[0] = 3,preSum = 3,remove = -3,hm = {0: 1, 3: 1}i = 1,num[1] = 1,preSum = 4,remove = -2,hm = {0: 1, 3: 1, 4: 1}i = 2,num[2] = 2,preSum = 6,remove = 0,cnt = 1,hm = {0: 1, 3: 1, 4: 1, 6: 1}i = 3,num[3] = 4,preSum = 10,remove = 4,cnt = 2,hm = {0: 1, 3: 1, 4: 2, 6: 1, 10: 1}i = 4,num[4] = -4,preSum = 6,remove = 0,cnt = 3,hm = {0: 1, 3: 1, 4: 2, 6: 2, 10: 1}i = 5,num[5] = -2,preSum = 4,remove = -2,cnt = 3,hm = {0: 1, 3: 1, 4: 3, 6: 2, 10: 1}
Result:
cnt = 3(subarrays:[3, 1, 2],[2, 4],[4, -4, -2, 4])
Example 2: num = {1, 1, 1}, k = 2
Initialization:
preSum = 0,hm = {0: 1},cnt = 0
Iteration:
i = 0,num[0] = 1,preSum = 1,remove = -1,hm = {0: 1, 1: 1}i = 1,num[1] = 1,preSum = 2,remove = 0,cnt = 1,hm = {0: 1, 1: 1, 2: 1}i = 2,num[2] = 1,preSum = 3,remove = 1,cnt = 2,hm = {0: 1, 1: 2, 2: 1, 3: 1}
Result:
cnt = 2(subarrays:[1, 1],[1, 1])
Time and Space Complexity
Time Complexity: O(n), where n is the length of the array, as we iterate through the array once.
Space Complexity: O(n), in the worst case, as the HashMap can store up to n distinct prefix sums.
This approach provides an efficient way to count subarrays with a specific sum using prefix sums and a HashMap. Happy coding!