class Solution:
def numSubarraysWithSum(self, nums, goal):
count = 0
prefix_counts = {0: 1}
prefix_sum = 0
for num in nums:
prefix_sum += num
count += prefix_counts.get(prefix_sum - goal, 0)
prefix_counts[prefix_sum] = prefix_counts.get(prefix_sum, 0) + 1
return count
class Solution {
public:
int numSubarraysWithSum(vector<int>& nums, int goal) {
unordered_map<int, int> prefix_counts;
prefix_counts[0] = 1;
int prefix_sum = 0, count = 0;
for (int num : nums) {
prefix_sum += num;
if (prefix_counts.find(prefix_sum - goal) != prefix_counts.end()) {
count += prefix_counts[prefix_sum - goal];
}
prefix_counts[prefix_sum]++;
}
return count;
}
};
class Solution {
public int numSubarraysWithSum(int[] nums, int goal) {
Map<Integer, Integer> prefixCounts = new HashMap<>();
prefixCounts.put(0, 1);
int prefixSum = 0, count = 0;
for (int num : nums) {
prefixSum += num;
count += prefixCounts.getOrDefault(prefixSum - goal, 0);
prefixCounts.put(prefixSum, prefixCounts.getOrDefault(prefixSum, 0) + 1);
}
return count;
}
}
var numSubarraysWithSum = function(nums, goal) {
let prefixCounts = {0: 1};
let prefixSum = 0, count = 0;
for (let num of nums) {
prefixSum += num;
count += (prefixCounts[prefixSum - goal] || 0);
prefixCounts[prefixSum] = (prefixCounts[prefixSum] || 0) + 1;
}
return count;
};
You are given a binary array nums
(an array containing only 0
s and 1
s) and an integer goal
. Your task is to count the number of non-empty, contiguous subarrays of nums
whose sum is exactly equal to goal
.
0
or 1
.
For example, if nums = [1,0,1,0,1]
and goal = 2
, the answer would be 4
.
The most straightforward way to solve this problem is to consider all possible subarrays, calculate their sums, and count those whose sum equals goal
. This brute-force approach, however, is inefficient for large arrays, as it checks every possible start and end index, resulting in a time complexity of O(n2).
To optimize, we look for patterns or properties we can exploit. Since the array contains only 0
s and 1
s, the sum of any subarray is simply the count of 1
s in that subarray. This property makes it possible to use prefix sums and hash maps to efficiently count the number of subarrays with a given sum.
The key insight is: for each position in the array, if we know how many times a prefix sum of current_sum - goal
has occurred before, we can add that many subarrays ending at the current position with sum equal to goal
.
We use a prefix sum approach combined with a hash map to efficiently count the number of subarrays whose sum equals goal
. Here’s how it works step by step:
prefix_counts
to keep track of how many times each prefix sum has occurred, starting with 0: 1
to account for subarrays starting at index 0.prefix_sum
to store the running sum as we iterate through nums
.count
to store the answer.nums
, add it to prefix_sum
.prefix_sum - goal
exists in prefix_counts
. If it does, add the number of times it has occurred to count
. This step finds all subarrays ending at the current index with sum equal to goal
.prefix_sum
in prefix_counts
.count
as the answer.
Why use a hash map? The hash map allows us to check in constant time how many times a particular prefix sum has occurred, which is crucial for efficiency.
Let's walk through the example nums = [1,0,1,0,1]
with goal = 2
:
prefix_counts = {0:1}
, prefix_sum = 0
, count = 0
prefix_sum = 1
. prefix_sum - goal = -1
(not in prefix_counts
). Update prefix_counts
to {0:1, 1:1}
.prefix_sum = 1
. prefix_sum - goal = -1
(not in prefix_counts
). Update prefix_counts
to {0:1, 1:2}
.prefix_sum = 2
. prefix_sum - goal = 0
(in prefix_counts
, count is 1). Add 1 to count
(count = 1
). Update prefix_counts
to {0:1, 1:2, 2:1}
.prefix_sum = 2
. prefix_sum - goal = 0
(in prefix_counts
, count is 1). Add 1 to count
(count = 2
). Update prefix_counts
to {0:1, 1:2, 2:2}
.prefix_sum = 3
. prefix_sum - goal = 1
(in prefix_counts
, count is 2). Add 2 to count
(count = 4
). Update prefix_counts
to {0:1, 1:2, 2:2, 3:1}
.
Final answer: count = 4
. The subarrays are [1,0,1], [0,1,0,1], [1,0,1,0], and [0,1].
The problem of counting binary subarrays with a given sum can be solved efficiently by leveraging prefix sums and a hash map. The key insight is that the number of subarrays ending at each position with sum equal to goal
is determined by how many times the prefix sum current_sum - goal
has occurred so far. This approach reduces the time complexity from quadratic to linear, making it suitable for large inputs.