You are given a binary array nums and an integer goal, return the number of non-empty subarrays with a sum goal.
A subarray is a contiguous part of the array.
Example 1:
Input: nums = [1,0,1,0,1], goal = 2
Output: 4Explanation: The 4 subarrays are bolded and underlined below:
[1,0,1,0,1]
[1,0,1,0,1]
[1,0,1,0,1]
[1,0,1,0,1]
Example 2:
Input: nums = [0,0,0,0,0], goal = 0
Output: 15Constraints:
1 <= nums.length <= 30,000nums[i] is either 0 or 1.0 <= goal <= nums.lengthBefore attempting this problem, you should be comfortable with:
The most straightforward approach is to check every possible subarray. For each starting index, we extend the subarray one element at a time, keeping track of the running sum. Whenever the sum equals the goal, we count it. Since the array contains only 0s and 1s, the sum can only increase as we extend the subarray.
i from 0 to n-1, initialize a running sum to 0.j from i to n-1, add nums[j] to the running sum.For a subarray from index i+1 to j to have sum equal to goal, we need prefixSum[j] - prefixSum[i] = goal, which means prefixSum[i] = prefixSum[j] - goal. As we iterate through the array computing prefix sums, we can use a hash map to count how many times each prefix sum has occurred. For each position, we check how many previous positions had a prefix sum that would give us our target subarray sum.
{0: 1} to handle subarrays starting from index 0.0.prefixSum - goal in the hash map and add its count to the result.class Solution:
def numSubarraysWithSum(self, nums: List[int], goal: int) -> int:
prefixSum = 0
count = { 0 : 1 } # prefixSum -> count
res = 0
for num in nums:
prefixSum += num
res += count.get(prefixSum - goal, 0)
count[prefixSum] = count.get(prefixSum, 0) + 1
return resSince the array contains only 0s and 1s, the prefix sum at any position is at most n (the array length). This allows us to use an array instead of a hash map for counting prefix sums. Array access is faster than hash map operations, making this approach more efficient in practice. The logic remains the same as the hash map approach.
n+1 to count prefix sums, initialized to 0.count[0] = 1 to handle subarrays starting from index 0.0.prefixSum >= goal, add count[prefixSum - goal] to the result.count[prefixSum].class Solution:
def numSubarraysWithSum(self, nums: List[int], goal: int) -> int:
n = len(nums)
count = [0] * (n + 1)
count[0] = 1
prefixSum, res = 0, 0
for num in nums:
prefixSum += num
if prefixSum >= goal:
res += count[prefixSum - goal]
count[prefixSum] += 1
return resCounting subarrays with exactly goal sum is tricky with a sliding window because shrinking the window might skip valid subarrays. However, counting subarrays with sum at most goal is straightforward. We can use the identity: count(exactly goal) = count(at most goal) - count(at most goal-1). For each right endpoint, we shrink the left side until the sum is at most the target, and all subarrays ending at right with starting points from left to right are valid.
x.left and right) with a running sum.right, add nums[right] to the sum. While sum > x, shrink from the left.(right - left + 1) to the count, representing all valid subarrays ending at right.helper(goal) - helper(goal - 1) as the final answer.class Solution:
def numSubarraysWithSum(self, nums: List[int], goal: int) -> int:
def helper(x):
if x < 0:
return 0
res = l = cur = 0
for r in range(len(nums)):
cur += nums[r]
while cur > x:
cur -= nums[l]
l += 1
res += (r - l + 1)
return res
return helper(goal) - helper(goal - 1)The hash map must start with {0: 1} to count subarrays that start from index 0. Without this, subarrays where the prefix sum exactly equals the goal are missed.
# Wrong: count = {}
# Correct: count = {0: 1}When using the sliding window approach, helper(goal - 1) becomes helper(-1). Without the early return for negative values, the window logic breaks and may produce incorrect results or infinite loops.
# Wrong: missing the x < 0 check
# Correct: if x < 0: return 0In the brute force approach, some incorrectly add a break when curSum > goal. This is wrong because the array contains only 0s and 1s, and adding more 0s keeps the sum unchanged, potentially finding more valid subarrays.