【中等】1248-统计优美子数组 Count Number of Nice Subarrays
题目
Given an array of integers nums and an integer k. A subarray is called nice if there are k odd numbers on it.
Return the number of nice sub-arrays.
Constraints:
1 <= nums.length <= 50000
1 <= nums[i] <= 10^5
1 <= k <= nums.length
给你一个整数数组 nums 和一个整数 k。
如果某个 连续 子数组中恰好有 k 个奇数数字,我们就认为这个子数组是「优美子数组」。
请返回这个数组中「优美子数组」的数目。
提示:
1 <= nums.length <= 50000
1 <= nums[i] <= 10^5
1 <= k <= nums.length
Example1
Input: nums = [1,1,2,1,1], k = 3
Output: 2
Explanation: The only sub-arrays with 3 odd numbers are [1,1,2,1] and [1,2,1,1].
Example2
Input: nums = [2,4,6], k = 1
Output: 0
Explanation: There is no odd numbers in the array.
Example3
Input: nums = [2,2,2,1,2,2,1,2,2,2], k = 2
Output: 16
来源:力扣(LeetCode)
链接:https://leetcode.com/problems/count-number-of-nice-subarrays
解法
方法:计算
解题思路
以第三个例子为例,之所以结果是16,是因为在子数组中,包含的2个奇数只有一种情况,就是第一个奇数为第一个1,最后一个奇数为第二个1,而子数组的开始和结尾既可以是对应的1,还可以是第一个1的前3个2和第二个1的后三个2,也就是说,有4种开始情况,4种结尾情况,组合结果为16种。
那么对于任意一组含有n个奇数的数组nums,想要子数组包含k个奇数,那么这k个奇数的选取一共有n-k+1种情况,每一种情况的子数组数都是(开头奇数前的偶数+1)*(结尾奇数后的偶数+1)
所以,只要我们知道每一个奇数前后有多少个连续偶数就可以计算出来了,对于n个奇数,可以得到n+1段连续偶数,对此,有两种方法可以采用:
-
用一个大小为n+1的数组记录奇数前后的偶数
-
记录每一个奇数的索引,前一个奇数-后一个奇数-1=中间的偶数个数,用大小为n+2的数组记录索引,第一位是-1,最后一位是nums.size()
代码
代码1:直接记录连续偶数个数
class Solution {
public:
int numberOfSubarrays(vector<int>& nums, int k) {
int size = nums.size(), list_num = 0;
vector<int> middle_num;
int num = 0;
for(int i = 0; i < size; ++i){
if(nums[i]%2 == 1){
middle_num.push_back(num+1);
num = 0;
}
else num++;
}
middle_num.push_back(num+1);
int odd_num = middle_num.size()-1;
if(k>odd_num) return 0;
for(int i = odd_num; i-k+1>0; --i){
list_num += (middle_num[i]*middle_num[i-k]);
}
return list_num;
}
};
代码2:记录奇数索引
class Solution {
public:
int numberOfSubarrays(vector<int>& nums, int k) {
vector<int> odd;
int num = 0, size = nums.size(), list_num = 0;
odd.push_back(-1);
for(int i = 0; i < size; ++i){
if(nums[i]%2==1) odd.push_back(i);
}
odd.push_back(size);
for(int i = 1; i+k<odd.size(); ++i){
list_num += ((odd[i]-odd[i-1])*(odd[i+k]-odd[i+k-1]));
}
return list_num;
}
};