每日一题,每日一练28.统计[优美子数组](有人相爱,有人半夜看海,有人早上八点写不出来)

编程入门 行业动态 更新时间:2024-10-21 19:44:21

每日一题,每日一练28.统计[优美子<a href=https://www.elefans.com/category/jswz/34/1771288.html style=数组](有人相爱,有人半夜看海,有人早上八点写不出来)"/>

每日一题,每日一练28.统计[优美子数组](有人相爱,有人半夜看海,有人早上八点写不出来)

统计「优美子数组」 给你一个整数数组 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

写了两个小时的滑动窗口,改了无数次条件,终于意识到了这不是仅仅要改窗口大小的事,被迫滚去看题解。然后又花了一个小时弄懂题解(我觉得各个学科都是不用专业名词很好懂)。简单解释一下。
由于数组中只有奇数有用,我们可以设立一个数组,用来记录第i个奇数前面带了几个偶数(不是奇数就是偶数)
比如[212221],第一个奇数前面带了一个偶数,第二个带了三个,所以数组是[1,3]

如果奇数不到k个,显然没有子数组,那么从第k个奇数开始,将每个奇数作为子数组的终点,因为子数组要有k个奇数,所以子数组第一个数如果是奇数必须是第一个奇数,这是极限状态,然后,我们发现这个子数组还可以在前面塞偶数,就是我们第一个奇数在数组的记录值。于是我们这样递推下去,对第i个奇数,可以组成的子数组都是极限状态+第i-k+1个奇数携带的偶数(可以塞在数组最前面

那么什么时候可以塞在最后面呢,这里我们还是基于极限状态来考虑。很显然,只有偶数能塞在极限状态的后面,如果我们塞进去一个奇数,就要修改极限状态

那么,当极限状态已经形成(统计已经到k个奇数时),如果遍历再获得奇数,我们当然记录到奇数数组并确立新的极限状态和状况**,如果是偶数,我们就可以插在之前极限状态的后面,这时候要注意,新增的符合条件的数组并不是加1,由于极限状态的前插和后插不互相干涉,我们可以认为之前的每种前插状况都可以和后插组成符合条件**

于是,我们的思路流程如下

记录每个奇数前面携带的偶数

从第i(i>=k)个奇数开始,把这个奇数作为子数组终点

由于子数组要有k个奇数,找到符合条件的第一个奇数(i-k)

确立子数组的极限状态,也就是两边都为奇数且奇数为k,不能再减少了

第一个奇数在前面能插入多少偶数,就有多少种满足条件的子数组

在存在极限状态后,分支如下:
如果接下来记录奇数,执行原思路流程

**如果接下来是偶数,叠加一次最近的极限状态满足条件的子数组,比如最近的奇数所确立的极限状态里第一个奇数前面携带4个偶数,则有极限状态+4种前插总计5个子数组,那么每后插一个偶数则咋满足条件的数目ans=ans+5

代码如下(官方的代码,因为再手撕好像变不出来什么新的花样了==0)

class Solution:def numberOfSubarrays(self, nums: List[int], k: int) -> int:cnt = [0] * (len(nums) + 1)cnt[0] =1odd, ans = 0, 0for num in nums:if num % 2 == 1:odd += 1if odd >= k:ans += cnt[odd - k]#cnt[odd] += 1#return ans
#作者:LeetCode-Solution
#链接:/
#来源:力扣(LeetCode)
#著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

注释太黑了我们按行解释一下

cnt = [0] * (len(nums) + 1) ### 创建奇数携带记录数组

cnt[0] =1 ##这里是给第一个奇数本身先占一个位置,也就是我们的极限状态

odd, ans = 0, 0 ## odd代表当前记录第几个奇数,ans代表答案

for num in nums: ##开始遍历原数组

if num % 2 == 1:#如果是奇数,意味着这个奇数已经被记录完成,因为这个奇数本身我们占过位了

odd += 1 #我们开始专注应对下一个奇数

if odd >= k:#如果已经有极限状态存在

ans += cnt[odd - k]#如果是奇数,我们将新的奇数当成子数组最后一个奇数,确立新的极限状态和可以前插的数目(odd位移过了),如果是偶数,我们叠加最新的极限状态可以前插的数目(理由如上)(odd没有位移

cnt[odd] += 1# 如果是奇数,这里为这个奇数占位,如果是偶数,增加这个奇数的携带偶数一个

return ans#循环整个数组后返回答案

现在再回去看看代码,是否清楚一点呢

有人相爱,有人半夜看海,有人早上八点写不出来

更多推荐

每日一题,每日一练28.统计[优美子数组](有人相爱,有人半夜看海,有人早上八点写不出来)

本文发布于:2024-02-26 10:35:09,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1702193.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:数组   八点   看海   优美   半夜

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!