来自Leetcode1248题统计优美子数组
给你一个整数数组 nums
和一个整数 k
。
如果某个 连续 子数组中恰好有 k
个奇数数字,我们就认为这个子数组是「优美子数组」。
请返回这个数组中「优美子数组」的数目。
示例 1:
1 | 输入:nums = [1,1,2,1,1], k = 3 |
滑动窗口
用一个辅助数组odd存放原数组nums里奇数位的下标,接着对odd数组遍历,取当前数值j(即原本nums数组里某奇数的下标为j)到其前一个奇数的距离(即odd[i] - odd[i-1])乘上后k个奇数的下标以及他能拓展的长度。
总的来说就是用数组存了2个指针,这2个指针刚好指向第一个奇数和第k个奇数,接下来再分别往前往后拓展,拓展相乘的结果就是当前k个连续奇数的可能情况,最后对所有结果再累加即可。
图来自力扣题解
将奇数的下标用数组储存,其中橘色部分为奇数出现的位置,蓝色部分标定数组的边界。对于每种子情形,其可能数为:(arr[i] - arr[i - 1]) * (arr[i + k] - arr[i + k - 1]),其中,左边界为−1,右边界为arr.length。
1 | class Solution { |
前缀和
来自sweetiee
- 计算前缀和数组
arr
:遍历原数组,每遍历一个元素,计算当前的前缀和(即到当前元素为止,数组中有多少个奇数); - 对上述前缀和数组,双重循环统计
arr[j] - arr[i] == k
的个数,这样做是 O(N^2)O(N2) 的(这里会超时哦)。 - 优化:因此,我们可以像「1. 两数之和」那样使用
HashMap
优化到 O(N),键是「前缀和」,值是「前缀和的个数」(下面代码中具体使用的是int[] prefixCnt
数组,下标是「前缀和」,值是「前缀和的个数」),因此我们可以遍历原数组,每遍历到一个元素,计算当前的前缀和sum
,就在res
中累加上前缀和为sum - k
的个数。 - 这里的前缀和指的是从0开始到当前元素这个区间的奇数的个数,所以两个前缀和的差就是两个元素之间的奇数的个数,我们要找的就是奇数个数为k的区间哈。prefixCnt数组是用来统计的是前缀和的个数,数组下标是前缀和,值是个数。如果当前的前缀数组的奇数个数为s2,那我们需要看有多少个前缀数组的奇数个数为 s1 = s2 - k 的,那么这些区间的奇数个数都是k,就累加到res中。
1 | class Solution { |