1248. 统计「优美子数组」

1248. 统计「优美子数组」

给你一个整数数组 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
package LeetCode;

/**
 * Q1248
 * 2020/4/21 22:09
 * 1248. 统计「优美子数组」
 *
 * 给你一个整数数组 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
 *
 *     思路:
 *     记录了每个奇数的下标,所以我们知道对于第 iii 个奇数,它的前一个奇数的下标为 odd[i−1]	extit{odd}[i-1]odd[i−1],
 *     也就是说 (odd[i−1],odd[i])(	extit{odd}[i-1],	extit{odd}[i])(odd[i−1],odd[i]) 间的数都为偶数。同理可得
 *     (odd[i+k−1],odd[i+k])(	extit{odd}[i+k-1],	extit{odd}[i+k])(odd[i+k−1],odd[i+k]) 间的数也都为偶数。
 *     那么我们可以得出满足 l∈(odd[i−1],odd[i]]lin (	extit{odd}[i-1],	extit{odd}[i]]l∈(odd[i−1],odd[i]]
 *     且 r∈[odd[i+k−1],odd[i+k])rin [	extit{odd}[i+k-1],	extit{odd}[i+k])r∈[odd[i+k−1],odd[i+k])
 *     条件的子数组 [l,r][l,r][l,r] 包含 [odd[i],odd[i+k−1]][	extit{odd}[i],	extit{odd}[i+k-1]][odd[i],
 *     odd[i+k−1]] 且 [l,r][l,r][l,r] 里的奇数个数为 kkk 个。因此对于第 iii 个奇数,它对答案的贡献为符合条件的
 *     [l,r][l,r][l,r] 的个数,即:
 *
 *          (odd[i]−odd[i−1])∗(odd[i+k]−odd[i+k−1])
 *      思路2:
 *      前缀和+差分
 * @Author m
 **/
public class Q1248 {
    public int numberOfSubarrays(int[] nums, int k) {
        /*//用于标记第i个奇数的位置
        int[] flag = new int[nums.length+2];
        //记录奇数的个数
        int n = 0;
        int res = 0;
        for (int i = 0; i < nums.length; i++) {
            if(nums[i]%2 == 1){
                flag[++n] = i;
            }
        }
        flag[0] = -1;
        flag[n+1] = nums.length;
        if(n < k) {
            return 0;
        }
        for(int i = 1; i <= n-k+1; i++){
            res += (flag[i] - flag[i-1])*(flag[i+k] - flag[i+k-1]);
        }
        return res;*/

        //前缀和+差分
        int n = nums.length;
        int[] cnt = new int[n+1];
        int odd = 0, ans = 0;
        cnt[0] = 1;
        for (int i = 0; i < n; ++i) {
            odd += nums[i] & 1;
            ans += odd >= k ? cnt[odd - k] : 0;
            cnt[odd] += 1;
        }
        return ans;
    }

    public static void main(String[] args) {
        System.out.println(new Q1248().numberOfSubarrays(new int[]{1,1,2,1,1}, 3));
    }
}
因为我喜欢追寻过程中的自己
原文地址:https://www.cnblogs.com/IzuruKamuku/p/14359791.html