class Solution {
public int numSubarrayProductLessThanK(int[] nums, int k) {
//k <=1 数组中没有满足条件的子数组
if(k <= 1){
return 0;
}
//l,r代表 左右指针
int l = 0;
int r = 0;
int sum = 1;
//ans 为满足条件的子数组个数
int ans = 0;
while (r < nums.length) {
//记录乘积
sum *= nums[r];
//当大于等于k,左指针右移并把之前左指针的数除掉
while (sum >= k) {
sum /= nums[l];
l++;
}
//每次右指针位移到一个新位置,应该加上 x 种数组组合:
// nums[right]
// nums[right-1], nums[right]
// nums[right-2], nums[right-1], nums[right]
// nums[left], ......, nums[right-2], nums[right-1], nums[right]
//共有 right - left + 1 种
ans += r - l + 1;
//右指针右移
r++;
}
return ans;
}
}
举例解释上述代码中 两个难理解的部分
//当大于等于k,左指针右移并把之前左指针的数除掉
while (sum >= k) {
sum /= nums[l];
l++;
}
ans += r - l + 1;
num = [10,2,5,6] k = 100
l,r = 0 sum = 1 ans = 0
l,r
10 2 5 6
sunm *= num[r] = 1*10 = 10
10 < k
本次产生新的满足条件的子数组为 [10]
ans += 0-0+1 = 0+1=1
r++
l r
10 2 5 6
sum *= num[r] = 10*2 = 20
20 < k
本次产生新的满足条件的子数组为 [2],[10,2]
ans = 1-0+1 = 1+2=3
r++
l r
10 2 5 6
sum *= num[r] = 20*5=100
100 <= k 满足进入循环条件
while(sum <= k){
//当sum <=k 成立时 表示此时[l,r]的乘积已经不满足条件 但之前[l,r-1]是满足条件的并已经统计过满足条件的子数组个数
// sum /= num[l] sum除去l的值 l++ l右移 开始统计另一个区间满足条件的子数组个数
sum /= num[l] = 100 /10 =10
l++
}
l r
10 2 5 6
10 < k 不满足循环条件 退出while循环
本次产生新的满足条件的子数组为 [5],[2,5]
ans += 2-1+1 = 3+2=5
r++
l r
10 2 5 6
sum *= num[r] = 10*6 = 60
60 < k
本次产生新的满足条件的子数组为 [6],[5,6] [2,5,6]
ans += 3-1+1 = 5+3 = 8
r++
r = num.length 循环结束
结果为8