一、題目介紹
給你一個整數數組 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
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
二、解題思路
- 遍歷數組記錄第i個奇數,在數組中的下標位置,保存在vOdd中。
- 利用滑動窗口的思想,保持一個含有k個奇數的“窗口”,即vOdd[i]到vOdd[i+k-1]之間的k個奇數。
- 設上述窗口中的左指針爲l,右指針爲r,則l的取值範圍爲(vOdd[i-1], vOdd[i] ];r的取值範圍爲[ vOdd[i+k-1], vOdd[i+k] )。[l,r]所對應下標之間的子數組即爲優美子數組。left = vOdd[i] - vOdd[i-1]代表第i-1個奇數到第i個奇數之間偶數的個數,同理right = vOdd[i+k] - vOdd[i+k-1]代表第i+k-1個奇數和第i+k個奇數之間偶數的個數。由此可以計算出,包含這k個奇數的子數組個數爲left * right。
- 遍歷vOdd,計算以第i個奇數爲起點的k個奇數,所能得到的優美子數組的累加和。
- 注意邊界情況的處理,詳細請見代碼。
三、解題代碼
class Solution {
public:
int numberOfSubarrays(vector<int>& nums, int k) {
int n = nums.size();
int cnt = 0;
vector<int> vOdd(n+2, -1);
for(int i = 0; i < n; ++i)
{
if((nums[i] & 1))
vOdd[++cnt] = i; //記錄第幾個奇數所對應的下標位置
}
vOdd[++cnt] = n;// 爲了統計最後一個奇數到數組結尾之間偶數的個數
int res = 0;
for(int i = 1; i + k <= cnt; ++i)
{
res += (vOdd[i] - vOdd[i-1])*(vOdd[i+k] - vOdd[i+k-1]);
}
return res;
}
};