思路和和大于或等于k的最短子数组差不多,都采用了窗口的思想。
初始时,两个指针都指向数组第一个元素,当left和right之间的子数组数字之积小于k时,向右移动指针right,当left和right之间的子数组数字之积大于k时,向右移动指针left。
由于目标是找出数字乘积小于k的子数组的个数,所以当移动right到某一位置时满足子数组的乘积小于k,不必再移动left,因为只要保持right不动,向又移动left所形成的所以子数组的数字乘积就一定小于k,那么一下子就找到了right-left+1个。
public static int numSubarrayProductLessThanK(int[] nums, int k) {
long product = 1; //子数组之积
int left = 0; //左指针,初始化指向第一个数字
int count = 0; //记录子数组个数
for (int right = 0; right < nums.length; right++) {
product *= nums[right];
while (left <= right && product >= k) {
//子数组之积大于或等于k,product先删除最左边的数后移动左指针
//并继续与k比较
product /= nums[left++];
}
//到这步,说明找到了一个满足条件的子数组,而该子数组的子数组也一定满足其积小于k
//所以可以直接增加子数组的子数组的个数right-left+1
count += right - left + 1;
}
return count;
}
时间复杂度为O(n),理由同和大于或等于k的最短子数组。