乘积小于 K 的子数组
难度:
标签:
题目描述
English description is not available for the problem. Please switch to Chinese.
代码结果
运行时间: 81 ms, 内存: 18.1 MB
/*
* 思路:
* 使用Java Stream实现与普通Java代码类似的逻辑。
* 由于Stream处理较为复杂的逻辑并不方便,我们还是采用滑动窗口算法。
*/
import java.util.stream.IntStream;
public class Solution {
public int numSubarrayProductLessThanK(int[] nums, int k) {
if (k <= 1) return 0;
int[] count = {0};
int[] product = {1};
int[] start = {0};
IntStream.range(0, nums.length).forEach(end -> {
product[0] *= nums[end];
while (product[0] >= k) {
product[0] /= nums[start[0]++];
}
count[0] += end - start[0] + 1;
});
return count[0];
}
}
解释
方法:
该题解采用了滑动窗口的方法来寻找所有乘积小于k的子数组。初始化两个指针left和right指向数组的起始位置,以及一个变量window_product来保存窗口内数字的乘积。向右移动right指针,扩大窗口,并更新window_product。如果window_product达到或超过了k,就逐渐移动left指针,缩小窗口,直到window_product小于k。每次当窗口的乘积有效(小于k)时,可以确定以right-1为结尾的子数组数量为right-left,因为每一个以right-1为结束点的子数组都有一个不同的起始点,这些起始点从left到right-1。因此,每次迭代中,都将这个长度加到结果answer中。
时间复杂度:
O(n)
空间复杂度:
O(1)
代码细节讲解
🦆
为什么在 k 小于等于 1 时直接返回 0 而不进一步处理数组中的元素?
▷🦆
滑动窗口的方法如何确保没有遗漏任何一个乘积小于 k 的子数组?
▷🦆
在窗口内乘积超过 k 时,为什么只是通过移动左指针来调整窗口大小,而不考虑其他方式如跳过某些元素?
▷