[LeetCode] 930. Binary Subarrays With Sum 二元子數組之和



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]
[1,0,1,0]
[0,1,0,1]
[1,0,1]

Note:

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

這道題給了我們一個只由0和1組成的數組A,還有一個整數S,問數組A中有多少個子數組使得其和正好為S。博主最先沒看清題意,以為是按二進制數算的,但是看了例子之后才發現,其實只是單純的求和而已。那么馬上就想着應該是要建立累加和數組的,然后遍歷所有的子數組之和,但是這個遍歷的過程還是平方級的復雜度,這道題的 OJ 卡的比較嚴格,只放行線性的時間復雜度。所以這種遍歷方式是不行的,但仍需要利用累加和的思路,具體的方法是在遍歷的過程中使用一個變量 curSum 來記錄當前的累加和,同時使用一個 HashMap,用來映射某個累加出現的次數,初始化需要放入 {0,1} 這個映射對兒,后面會講解原因。在遍歷數組的A的時候,對於每個遇到
的數字 num,都加入累加和 curSum 中,然后看若 curSum-S 這個數有映射值的話,那么說明就存在 m[curSum-S] 個符合題意的子數組,應該加入到結果 res 中,假如 curSum 正好等於S,即 curSum-S=0 的時候,此時說明從開頭到當前位置正好是符合題目要求的子數組,現在明白剛開始為啥要加入 {0,1} 這個映射對兒了吧,就是為了處理這種情況。然后此時 curSum 的映射值自增1即可。其實這道題的解法思路跟之前那道 Contiguous Array 是一樣的,那道題是讓找0和1個數相同的子數組,這里讓找和為S的子數組,都可以用一個套路來解題,參見代碼如下:


解法一:

class Solution {
public:
    int numSubarraysWithSum(vector<int>& A, int S) {
        int res = 0, curSum = 0;
        unordered_map<int, int> m{{0, 1}};
        for (int num : A) {
            curSum += num;
            res += m[curSum - S];
            ++m[curSum];
        }
        return res;
    }
};

我們也可以使用滑動窗口 Sliding Window 來做,也是線性的時間復雜度,其實還是利用到了累計和的思想,不過這個累加和不是從開頭到當前位置之和,而是這個滑動窗口內數字之和,這 make sense 吧,因為只要這個滑動窗口內數字之和正好等於S了,即是符合題意的一個子數組。遍歷數組A,將當前數字加入 sum 中,然后看假如此時 sum 大於S了,則要進行收縮窗口操作,左邊界 left 右移,並且 sum 要減去這個移出窗口的數字,當循環退出后,假如此時 sum 小於S了,說明當前沒有子數組之和正好等於S,若 sum 等於S了,則結果 res 自增1。此時還需要考慮一種情況,就是當窗口左邊有連續0的時候,因為0並不影響 sum,但是卻要算作不同的子數組,所以要統計左起連續0的個數,並且加到結果 res 中即可,參見代碼如下:


解法二:

class Solution {
public:
    int numSubarraysWithSum(vector<int>& A, int S) {
        int res = 0, sum = 0, left = 0, n = A.size();
        for (int i = 0; i < n; ++i) {
            sum += A[i];
            while (left < i && sum > S) sum -= A[left++];
            if (sum < S) continue;
            if (sum == S) ++res;
            for (int j = left; j < i && A[j] == 0; ++j) {
                ++res;
            }
        }
        return res;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/930


參考資料:

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

https://leetcode.com/problems/binary-subarrays-with-sum/discuss/276976/C%2B%2B

https://leetcode.com/problems/binary-subarrays-with-sum/discuss/186683/C%2B%2BJavaPython-Sliding-Window-O(1)-Space


LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM