题目
Your are given an array of positive integers nums.
Count and print the number of (contiguous) subarrays where the product of all the elements in the subarray is less than k.
Example 1:
Input: nums = [10, 5, 2, 6], k = 100
Output: 8
Explanation: The 8 subarrays that have product less than 100 are: [10], [5], [2], [6], [10, 5], [5, 2], [2, 6], [5, 2, 6].
Note that [10, 5, 2] is not included as the product of 100 is not strictly less than k.
Note:
0 < nums.length <= 50000.
0 < nums[i] < 1000.
0 <= k < 10^6.
思路
最开始做的暴力循环,从每个index开始,找到右边能找的最远的位置,然后一个全部都是1的test case失败,考虑到下一次需要利用上一次的计算结果而不是直接找。
原来的思路其实是先大问题再小问题,是不能利用前者的结果的,就考虑从最靠右侧的index开始,往左加一个数问题扩大,product *= nums[index - 1]
,这样我们就利用了上一步计算的product来计算当前的product,而此时product是增大的,也就是说原来我的product是从
n
u
m
s
[
i
]
⋅
.
.
.
⋅
n
u
m
s
[
j
]
nums[i] \cdot ... \cdot nums[j]
nums[i]⋅...⋅nums[j],这个时候新的product是从
n
u
m
s
[
i
−
1
]
⋅
.
.
.
⋅
n
u
m
s
[
j
]
nums[i-1] \cdot ... \cdot nums[j]
nums[i−1]⋅...⋅nums[j],因为要找到右边的这个最大的j的值,且product递增,这个j不会比上次的j还要大,否则上一次找到的就不是最远成立的j,所以j只会不变或变小。当新的product依然满足小于k时,j不变,此时从i开始的子列有
(
n
u
m
s
[
i
−
1
]
)
,
(
n
u
m
s
[
i
−
1
]
,
n
u
m
s
[
i
]
)
,
.
.
.
,
(
n
u
m
s
[
i
−
1
]
⋅
.
.
.
⋅
n
u
m
s
[
j
]
)
(nums[i - 1]), (nums[i - 1], nums[i]), ..., (nums[i-1] \cdot ... \cdot nums[j])
(nums[i−1]),(nums[i−1],nums[i]),...,(nums[i−1]⋅...⋅nums[j]),共有j-i+1个;当新的product大于等于k时,不断去掉最右边的数,缩小j的值,直到满足要求。
下面的代码是从反方向来的但是思路一样。
代码
class Solution {
public int numSubarrayProductLessThanK(int[] nums, int k) {
int res = 0, product = 1, left = 0;
for (int i = 0; i < nums.length; i++) {
product *= nums[i];
while (product >= k && left <= i) {
product /= nums[left++];
}
res += i - left + 1;
}
return res;
}
}