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));
}
}