描述
给你一个整数数组 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
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/subarray-product-less-than-k
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这道题,我属实有心理阴影….在我刚开始做题的时候…

一遍一遍提交,都不通过…提交的次数比这个多,只不过没有显示全【红色的】,绝望的一批 (ノ`Д)ノ,颇有想掀桌子的冲动,然后今天又碰到这题了,虽然一次通过了,但仍心有余悸…o(≧口≦)o【仍想了挺久的】然后记录一下题解…整理一下思路
思路
首先这个题要求的是乘积,就不能用数组前缀乘积
了,因为一直乘积可能会超过int的范围,虽然可以用 长整型long
,但不建议这么用。【这是我第一次做题的时候的思路,还是太年轻,因为每次看到数组滑窗
,总会想到前缀和
】
既然是滑窗,就得定义窗口左右的指针
1 | int left = -1,right = 0; |
初始化窗口的乘积
以及连续子数组的数目
1 | int mult = nums[0]; //注意,数组的长度是大于等于1的 |
当窗口的乘积<k时
- 连续子数组的数目 加上 窗口的大小
result+=(right-left);
【?为什么加上窗口的大小呢,稍后图示说明,感觉这个应该算是题的一个难点吧】 - 然后右边扩大窗口
right++;mult*=nums[right];
- 连续子数组的数目 加上 窗口的大小
当窗口乘积>=k时
左边窗口缩小
left++;mult/=nums[left];
注意,有可能这个左边窗口缩小到
left>=right
,那就需要扩大右边的窗口了right++;mult*=nums[right];
。1
2
3
4if(left>=right){
right++;
mult*=nums[right];
}
以nums = [10,5,2,6], k = 100
为例。
result+=1
,子数组是[10]
result+=2
,子数组是[10,5],[5]
窗口子数组就没有严格小于k,缩小窗口。
result+=2
,子数组是[5,2],[2]
result+=2
,子数组是[5,2,6],[2,6],[6]
由于窗口已经到达边界,所以结束,result=8
代码
1 | class Solution { |
但仍然有个问题,你可以把上述代码运行一下,不出意外的话,应该是出意外了。嘿嘿嘿ο(=•ω<=)ρ⌒☆
java.lang.ArrayIndexOutOfBoundsException
数组越界了。在循环过程中
1 | while (right<nums.length){ |
所以需要把mult*=nums[right];
,改为if(right<nums.length) mult*=nums[right];
。
代码
1 | class Solution { |
__END__