algorithm-base/animation-simulation/前缀和/leetcode1248寻找优美子数组.md
2021-04-27 15:11:05 +08:00

154 lines
5.2 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

> 如果阅读时发现错误或者动画不可以显示的问题可以添加我微信好友 **[tan45du_one](https://raw.githubusercontent.com/tan45du/tan45du.github.io/master/个人微信.15egrcgqd94w.jpg)** ,备注 github + 题目 + 问题 向我反馈
>
> 感谢支持该仓库会一直维护希望对各位有一丢丢帮助
>
> 另外希望手机阅读的同学可以来我的 <u>[**公众号袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入。
#### [1248. 统计优美子数组](https://leetcode-cn.com/problems/count-number-of-nice-subarrays/)
**题目描述**
> 给你一个整数数组 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
如果上面那个题目我们完成了这个题目做起来分分钟的事不信你去写一哈百分百就整出来了我们继续按上面的思想来解决
**HashMap**
**解析**
上个题目我们是求和为 K 的子数组这个题目是让我们求 恰好有 k 个奇数数字的连续子数组这两个题几乎是一样的上个题中我们将前缀区间的和保存到哈希表中这个题目我们只需将前缀区间的奇数个数保存到区间内即可只不过将 sum += x 改成了判断奇偶的语句见下图
![微信截图_20210114222339](https://cdn.jsdelivr.net/gh/tan45du/github.io.phonto2@master/myphoto/微信截图_20210114222339.c0gwtdh8m94.png)
我们来解析一下哈希表key 代表的是含有 1 个奇数的前缀区间value 代表这种子区间的个数含有两个也就是nums[0],nums[0,1].后面含义相同那我们下面直接看代码吧一下就能读懂
Java Code:
```java
class Solution {
public int numberOfSubarrays(int[] nums, int k) {
if (nums.length == 0) {
return 0;
}
HashMap<Integer,Integer> map = new HashMap<>();
//统计奇数个数,相当于我们的 presum
int oddnum = 0;
int count = 0;
map.put(0,1);
for (int x : nums) {
// 统计奇数个数
oddnum += x & 1;
// 发现存在,则 count增加
if (map.containsKey(oddnum - k)) {
count += map.get(oddnum - k);
}
//存入
map.put(oddnum,map.getOrDefault(oddnum,0)+1);
}
return count;
}
}
```
C++ Code:
```cpp
class Solution {
public:
int numberOfSubarrays(vector<int>& nums, int k) {
if (nums.size() == 0) {
return 0;
}
map <int, int> m;
//统计奇数个数,相当于我们的 presum
int oddnum = 0;
int count = 0;
m.insert({0,1});
for (int & x : nums) {
// 统计奇数个数
oddnum += x & 1;
// 发现存在,则 count增加
if (m.find(oddnum - k) != m.end()) {
count += m[oddnum - k];
}
//存入
if(m.find(oddnum) != m.end()) m[oddnum]++;
else m[oddnum] = 1;
}
return count;
}
};
```
但是也有一点不同就是我们是统计奇数的个数数组中的奇数个数肯定不会超过原数组的长度所以这个题目中我们可以用数组来模拟 HashMap 用数组的索引来模拟 HashMap key用值来模拟哈希表的 value下面我们直接看代码吧
Java Code:
```java
class Solution {
public int numberOfSubarrays(int[] nums, int k) {
int len = nums.length;
int[] map = new int[len + 1];
map[0] = 1;
int oddnum = 0;
int count = 0;
for (int i = 0; i < len; ++i) {
//如果是奇数则加一偶数加0相当于没加
oddnum += nums[i] & 1;
if (oddnum - k >= 0) {
count += map[oddnum-k];
}
map[oddnum]++;
}
return count;
}
}
```
C++ Code:
```cpp
class Solution {
public:
int numberOfSubarrays(vector<int>& nums, int k) {
int len = nums.size();
vector <int> map(len + 1, 0);
map[0] = 1;
int oddnum = 0;
int count = 0;
for (int i = 0; i < len; ++i) {
//如果是奇数则加一偶数加0相当于没加
oddnum += nums[i] & 1;
if (oddnum - k >= 0) {
count += map[oddnum-k];
}
map[oddnum]++;
}
return count;
}
};
```