leetcode1248. 統計「優美子數組」

給你一個整數數組 nums 和一個整數 k。

如果某個 連續 子數組中恰好有 k 個奇數數字,我們就認爲這個子數組是「優美子數組」。

請返回這個數組中「優美子數組」的數目。

示例 1:

輸入:nums = [1,1,2,1,1], k = 3
輸出:2
解釋:包含 3 個奇數的子數組是 [1,1,2,1][1,2,1,1]

示例 2:

輸入:nums = [2,4,6], k = 1
輸出:0
解釋:數列中不包含任何奇數,所以不存在優美子數組。

示例 3:

輸入:nums = [2,2,2,1,2,2,1,2,2,2], k = 2
輸出:16

提示:

  • 1 <= nums.length <= 50000
  • 1 <= nums[i] <= 10^5
  • 1 <= k <= nums.length

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/count-number-of-nice-subarrays
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

基本思想

滑動窗口

  • 從頭到尾遍歷數組,找到滿足要求的最小子串
  • 統計子串兩端連續偶數的個數,例如右邊 r 個,左邊 l 個,那麼由當前最小子串構成的優美子數組有 (r + 1) x (l + 1) 個
class Solution {
public:
    int numberOfSubarrays(vector<int>& nums, int k) {
        //找到一個優美子數組向兩端擴展,統計個數,用乘法的形式左面三個右面三個4x4
        //然後再從第二個奇數所構成的優美數組向兩端擴展
        
        if(nums.size() == 0 || k > nums.size())
            return 0;
        
        int res = 0;
        deque<int> pos;
        int s = 0;
        for(int i = 0; i < nums.size(); ++i){
            if(nums[i] & 1){
                pos.push_back(i);//保存奇數的下標
            }
            if(pos.size() == k){
                int l = pos.front() - s;//左面偶數的個數
                int r = 0;
                int k = i + 1;
                //統計右面連續偶數的個數
                while(k < nums.size() && ((nums[k] & 1) == 0)){
                    ++r; 
                    ++k;
                }
                //cout << i << " " <<  l << " " << r << endl;
                res += (l + 1) * (r + 1);
                if(k == nums.size())
                    break;
                s = pos.front() + 1;
                pos.pop_front();
            }
        }
        return res;
    }
};

前綴和

  • 統計以當前元素結尾的序列中優美子數組的個數
  • 遍歷數組的過程中,統計前 i 個數字中奇數的個數
  • 如果奇數的個數 odd大於等於 k,需要統計前 i 個數字中有多少個奇數個數爲odd - k的子序列,有幾個就說明能構成幾個優美子數組(這裏不太好理解,參考:官方題解)
class Solution {
public:
    int numberOfSubarrays(vector<int>& nums, int k) {
        vector<int> cnt(nums.size() + 1, 0);
        cnt[0] = 1;
        int odd = 0;//統計前i個數中奇數的個數
        int res = 0;
        for(int i = 0; i < nums.size(); ++i){
            odd += (nums[i] & 1);
            res += ((odd >= k ? cnt[odd - k] : 0));
            cnt[odd]++;
        }
        return res;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章