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
hm
with(0, 1)
because an empty subarray has a sum of 0.
Iterate Through the Array:
For each element
num[i]
in the array:Update
preSum
by addingnum[i]
.Calculate
remove = preSum - k
. Ifhm
containsremove
, it means there's a prefix sum that, when subtracted from the currentpreSum
, equalsk
. This indicates a subarray with sumk
.Increment
cnt
by the frequency ofremove
inhm
.Update the frequency of the current
preSum
inhm
.
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!