【中等】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段连续偶数,对此,有两种方法可以采用:

  1. 用一个大小为n+1的数组记录奇数前后的偶数

  2. 记录每一个奇数的索引,前一个奇数-后一个奇数-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;
    }
};
posted @ 2020-04-21 13:58  陌良  阅读(222)  评论(0编辑  收藏  举报