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 <= 500001 <= nums[i] <= 10^51 <= k <= nums.length
来源:LeetCode
链接:https://leetcode-cn.com/problems/count-number-of-nice-subarrays
我的思路:
1、数组nums中的个数小于k,返回0
2、遍历数组,内层从当前位继续遍历数组,当内层遍历到有k个奇数时,resNum++
3、内层继续向后遍历,直到碰到下一个数组中的奇数停止,否则一直执行 resNum++
ps:leetcode上,执行没问题,也就是这个方法没问题,但是提交的后,显示超时失败,也就是说方法太垃圾了,碰到比较长的数组时,运行时间太长了。
/*** @param {number[]} nums* @param {number} k* @return {number}*/var numberOfSubarrays = function(nums, k) {if(k > nums.length) return 0;let resNum = 0;const n = nums.length-k+1;const m = nums.length;for(let i = 0; i < n; i++ ){let odd_number = 0;let isreturn = 0;for(let j = i; j < m; j++){if(nums[j]%2 && isreturn == 1) break;if(nums[j]%2) odd_number++;if(odd_number == k){resNum++;isreturn = 1;}}}return resNum;};
没办法,只能是去看看题解了,题解中,有人提出,使用动态规划的方法来解决问题。get到了一个新的算法,动态规划。
新的解法
1、遍历整个数组,每当碰到奇数,将它是第几个数保存在 oddIdxArr 中
2、当保存的个数大于等于k个,计算 oddIdxArr 中的第 oddIdxArr.length - k 个和它前一个的差值,这个差值,即为个数。
举例说明:
nums = [2,1,2,1,1] k = 2
i = 0 oddIdxArr=[]
i = 1 oddIdxArr=[2]
i = 2 oddIdxArr=[2]
i = 3 oddIdxArr=[2,4]
个数达到k个,当前 res = 2 - 0
i = 4 oddIdxArr=[2,4,5]
个数大于k个,(2,4)共存已经计算过,当前计算(4,5)共存的情况,res += 4-2
var numberOfSubarrays = function(nums, k) {const oddIdxArr = [];let res = 0;let len = nums.length;for (let i = 0; i < len; i++) {if (nums[i] % 2) {oddIdxArr.push(i + 1);}if (oddIdxArr.length >= k) {// ~~ false undefined 等进行两次去翻,值为 0// 这里是用于处理第一次达到k个数字时出现的边界情况res += oddIdxArr[ oddIdxArr.length - k ] - ~~oddIdxArr[ oddIdxArr.length - k - 1 ];}}return res;};
