题目来源
题目描述
class Solution {
public:
int numSubarrayProductLessThanK(vector<int>& nums, int k){
}
};
题目解析
分析
如样例所示,nums = [10,5,2,6], k = 100,一共有8种子数组。
我们可以发现一个规律:
- 如果一个子数组的乘积小于k,那么它的每个子集的乘积都会小于k
- 假如这个子数组的下标范围为[left,right],那么一共由right - left + 1的子集(子数组的长度),这样我们就一次性的统计出了right - left + 1种方案
因此我们可以定义两个指针left,right:
- [left,right]组成滑动窗口,left是左边界,right是右边界。
- 遍历整个nums数组,对于每个右边界right,都去找一个最小的左边界left,使得[left,right]子数组的乘积小于k,然后答案累加上right - left + 1,这样就可以不重不漏的求完所有的方案
实现
class Solution {
public:
int numSubarrayProductLessThanK(vector<int>& nums, int k) {
int res = 0, p = 1, left = 0;
for(int i = 0; i < nums.size(); i++){
p *= nums[i];
while(left <= i && p >= k)
p /= nums[left++];
res += i - left + 1;
}
return res;
}
};
类似题目
题目 | 思路 |
---|---|
leetcode:53. 子数组最大累加和是多少 maximum-subarray | 动态规划、线段和、贪心 |
leetcode:713. 乘积小于 K 的子数组个数subarray-product-less-than-k | 滑动窗口 |