携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第24天,点击查看活动详情
每日刷题 2022.08.22
- leetcode原题链接:leetcode.cn/problems/ZV…
- 难度:中等
- 方法: 滑动窗口
题目
- 给定一个正整数数组
nums和整数k,请找出该数组内乘积小于k的连续的子数组的个数。
示例
- 示例1
输入: nums = [10,5,2,6], k = 100
输出: 8
解释: 8 个乘积小于 100 的子数组分别为: [10], [5], [2], [6], [10,5], [5,2], [2,6], [5,2,6]。
需要注意的是 [10,5,2] 并不是乘积小于100的子数组。
- 示例2
输入: nums = [1,2,3], k = 0
输出: 0
提示
1 <= nums.length <= 3 * 1041 <= nums[i] <= 10000 <= k <= 106
解题思路
- 使用滑动窗口的容斥原理。双指针实现的滑动窗口,右指针一直往后,直到区间内包含的元素不符合要求,就移动左区间的指针,缩小区间,直到区间包含的元素再次符合要求时,停止左区间的移动,再移动右区间的指针。
- 初始化 l 和 r 两个指针,同时从 0 开始
- r 向右遍历,直到 r = nums.length - 1
- 如果 r 小于 k, 表示 r 当前这个数单独满足要求,答案 + 1
- 此时 while 循环将 l 左移,每次判断是否满足乘积小于 k,满足答案 + 1
- 直到乘积大于等于 k,无法进入 while 循环
- 收回 l, 与 r 同步右移,重复上述步骤
AC代码
var numSubarrayProductLessThanK = function(nums, k) {
// 使用滑动窗口,每次新添加进来的长度,新增加的个数,就是当前的下标差值
let n = nums.length, ans = 0;
if(k <= 1) return 0;
for(let i = 0, j = 0, multi = 1; i < n; i++) {
multi *= nums[i];
console.log(multi)
while(multi >= k) {
multi /= nums[j++];
}
// 当前的数值的长度, 总的都会加上的
ans += i - j + 1;
}
return ans;
};