难度中等496收藏分享切换为英文接收动态反馈
给你一个整数数组 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 * 104
1 <= nums[i] <= 1000
0 <= k <= 106
通过次数63,820提交次数134,347
题解:这题说的是找出子数组内所有元素的乘积严格小于k的连续子数组的数目。我们可以使用滑动窗口来解决,使用两个指针,一个指向窗口的右边,一个指向窗口的左边,窗口内所有元素的乘积必须小于k。如果窗口内元素的乘积大于等于k,我们就移动窗口的左边界……直到窗口内所有元素的乘积小于k为止。而满足条件的子数组的数目我们以窗口右边界为结尾的子数组数量,这样做的目的主要是为了防止重复统计。如果一个子串的乘积小于k,那么他的每个子集都小于k,而一个长度为n的数组,他的所有连续子串数量是1+2+...n
,但是会和前面的重复。 比如例子中[10, 5, 2, 6]
,第一个满足条件的子串是[10]
,第二个满足的是[10, 5]
,但是第二个数组的子集[10]
和前面的已经重复了,因此我们只需要计算包含最右边的数字的子串数量,就不会重复了,也就是在计算[10, 5]
这个数组的子串是,只加入[5]
和[10, 5]
,而不加入[10]
,这部分的子串数量刚好是r - l + 1
感谢网友对题目的评论和公众号的支持:671,滑动窗口解乘积小于 K 的子数组
最后的代码如下:
class Solution {
public:
int numSubarrayProductLessThanK(vector<int>& nums, int k) {
if(k == 0 || k == 1) return 0;
int l = 0;
int prod = 1; //存储nums[l]~nums[r]的累积
int res = 0;
for(int r = 0; r < nums.size(); r++){
prod *= nums[r];
while(prod >= k){
prod /= nums[l++];
}
res += r - l + 1;
}
return res;
}
};
还是挺巧妙的,如果进阶一下,将符合情况的子序列都返回,该怎么操作呢?