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: 4 Explanation: 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: 15
Constraints:
1 <= nums.length <= 3 * 104
nums[i]
is either 0
or 1
.0 <= goal <= nums.length
The problem asks to find the number of non-empty subarrays with a sum equal to a given goal
. Two efficient solutions are presented below: using a prefix sum and a sliding window approach.
This solution leverages the concept of prefix sums and a hash table (dictionary in Python) to efficiently count subarrays.
Approach:
prefix sum
s
. As we iterate through the array, s
accumulates the sum of elements encountered so far.cnt
stores the frequency of each prefix sum encountered. We initialize cnt[0] = 1
because an empty subarray has a sum of 0.v
, we update the prefix sum s += v
. Then, we check if s - goal
exists as a key in cnt
. If it does, it means there's a previous prefix sum that, when added to a subarray ending at the current position, results in the goal
sum. The number of such subarrays is given by cnt[s - goal]
. We add this count to the ans
.s
in cnt
.Time Complexity: O(N), where N is the length of the input array nums
. We iterate through the array once. Hash table operations (insertion and lookup) take O(1) on average.
Space Complexity: O(N) in the worst case, as the hash table might store all unique prefix sums.
Code (Python):
from collections import Counter
class Solution:
def numSubarraysWithSum(self, nums: List[int], goal: int) -> int:
cnt = Counter({0: 1}) # Initialize with empty subarray sum
ans = s = 0
for v in nums:
s += v
ans += cnt[s - goal] # Count subarrays with sum equal to goal
cnt[s] += 1 # Update frequency of current prefix sum
return ans
Other languages (Java, C++, Go, JavaScript) follow a very similar structure, utilizing their respective hash table implementations.
This approach uses two sliding windows to count subarrays with sums greater than or equal to the goal
.
Approach:
i1
and i2
, representing the start of two sliding windows. i1
tracks the window with a sum strictly greater than goal
, and i2
tracks the window with a sum greater than or equal to goal
.j
pointer. For each element, we update the sums s1
(for i1
) and s2
(for i2
). We adjust i1
and i2
to maintain the conditions on their respective sums.i2 - i1
represents the number of subarrays ending at position j
with a sum equal to goal
. We add this difference to the ans
.Time Complexity: O(N), as we iterate through the array once. The inner while
loops do not increase the time complexity beyond linear.
Space Complexity: O(1). We only use a few constant extra variables.
Code (Python):
class Solution:
def numSubarraysWithSum(self, nums: List[int], goal: int) -> int:
i1 = i2 = s1 = s2 = j = ans = 0
n = len(nums)
while j < n:
s1 += nums[j]
s2 += nums[j]
while i1 <= j and s1 > goal:
s1 -= nums[i1]
i1 += 1
while i2 <= j and s2 >= goal:
s2 -= nums[i2]
i2 += 1
ans += i2 - i1
j += 1
return ans
Again, other languages have very similar implementations using the sliding window technique. Both solutions offer efficient and optimized ways to solve this problem, with the prefix sum approach generally being slightly easier to understand. The sliding window approach might offer a marginal performance advantage in specific cases.