# 930. Binary Subarrays With Sum

**<font color=red>难度: Medium</font>**

## 刷题内容

> 原题连接

* https://leetcode.com/problems/binary-subarrays-with-sum/description/

> 内容描述

```

In an array A of 0s and 1s, how many non-empty subarrays have sum S?

 

Example 1:

Input: A = [1,0,1,0,1], S = 2
Output: 4
Explanation: 
The 4 subarrays are bolded below:
[1,0,1,0,1]
[1,0,1,0,1]
[1,0,1,0,1]
[1,0,1,0,1]
 

Note:

A.length <= 30000
0 <= S <= A.length
A[i] is either 0 or 1.
```

## 解题方案

> 思路 1
******- 时间复杂度: O(N^2)******- 空间复杂度: O(1)******

双指针，worst case是A中所有数字全为0，那么是O(N^2)

beats 9.65%

```python
class Solution(object):
    def numSubarraysWithSum(self, A, S):
        """
        :type A: List[int]
        :type S: int
        :rtype: int
        """
        start, end, cur_sum, res = 0, 0, 0, 0
        while end < len(A):
            cur_sum += A[end]
            while start < end and cur_sum > S:
                cur_sum -= A[start]
                start += 1
            if cur_sum == S:
                res += 1
                tmp = start
                while tmp < end and A[tmp] == 0:
                    res += 1
                    tmp += 1
            end += 1
        return res
```

> 思路 2
******- 时间复杂度: O(N)******- 空间复杂度: O(1)******

另外一个版本的双指针，我每次算一下end可以前进的长度于start可以前进的长度的乘积加到res上就可以了，这样start和end前进的更快

但是处理S=0的情况会有问题，需要单独处理

```python
class Solution(object):
    def numSubarraysWithSum(self, A, S):
        """
        :type A: List[int]
        :type S: int
        :rtype: int
        """
        if S == 0:
            return self.solveZero(A)
        
        res = 0
        cur_sum = 0
        start, end = 0, 0
                
        while start < len(A) and end < len(A):
            cur_sum += A[end]
            end += 1
            if cur_sum == S:
                res += 1
                cur_end = end
                while end < len(A) and A[end] == 0:
                    res += 1
                    end += 1
                cur_start = start
                while start < cur_end and A[start] == 0:
                    res += 1
                    start += 1
                res += (start-cur_start) * (end-cur_end)
                end = cur_end
                cur_sum -= A[start]
                start += 1
            # print(res)
        return res
    
    def solveZero(self, A):
        res = 0
        count_zero = 0
        for num in A:
            if num == 0:
                count_zero += 1
                res += count_zero
            else:
                count_zero = 0
        return res
```



> 思路 3
******- 时间复杂度: O(N)******- 空间复杂度: O(N)******

一看到subarray sum，立马要想到前缀和，虽然我第一想法是双指针，但是双指针处理S=0的情况估计会有问题，先写一下前缀和解法


遍历前缀和数组，找前面有几个前缀和的值等于 ```当前前缀和 - S```，就说明以当前index为结尾的subarray有几个满足和为S

```python
class Solution(object):
    def numSubarraysWithSum(self, A, S):
        """
        :type A: List[int]
        :type S: int
        :rtype: int
        """
        if not A or len(A) == 0:
            return 0
        if sum(A) < S:
            return 0
        
        prefix = [A[0]] * len(A)
        for i in range(1, len(A)):
            prefix[i] = prefix[i-1] + A[i]
        
        res, lookup = 0, {0:1}
        for idx, num in enumerate(prefix):
            res += lookup.get(num-S, 0)
            lookup[num] = lookup.get(num, 0) + 1
        return res
```

或者写的更简洁一些，[寒神](https://leetcode.com/problems/binary-subarrays-with-sum/discuss/186683/C++JavaPython-Straight-Forward)
的版本

```python
class Solution(object):
    def numSubarraysWithSum(self, A, S):
        """
        :type A: List[int]
        :type S: int
        :rtype: int
        """
        c = collections.Counter({0: 1})
        psum = res = 0
        for num in A:
            psum += num
            res += c[psum - S]
            c[psum] += 1
        return res
```

换一种思路，反过来写

```python
class Solution(object):
    def numSubarraysWithSum(self, A, S):
        """
        :type A: List[int]
        :type S: int
        :rtype: int
        """
        c = collections.defaultdict(int)
        res = psum = 0
        for x in A:
            c[psum + S] += 1
            psum += x
            res += c[psum]
        return res
```

























