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.
找出子数组,使子数组里所有元素的乘积绝对小于k,返回这样的子数组的个数
思路:
数组长度在50000数量级,遍历所有的子数组组合是不行的。
子数组是连续的,不能改变元素的顺序。因此不能排序。
用slide window的方法
固定住子数组右边界的元素,滑动左边,
当子数组内所有元素乘积>=k时,就把左边的元素滑出去,乘积把左边元素除掉。这时候包含右边元素的子数组个数就是right - left + 1, 这里right,left指的是右边界元素和左边界元素的index,
比如[5,2,6], 包含6的子数组有它本身[6], 向左扩一个[2, 6], 再扩一个[5,2,6], 就是这个子数组的长度right - left + 1
逐步移动右边界即可
注意左边界只需要初始化一次,初始化为0, 后面左边界向右移动后不需要再初始化,
因为,比如[10, 5, 2, 6], 在右边界移动到2时,左边的10要移出,因为10x5x2 >= 100了,那么右边界再向右移时乘积还要再乘6,自然更不需要移掉的10了
public int numSubarrayProductLessThanK(int[] nums, int k) {
if(nums == null || nums.length == 0 || k <= 1) {
return 0;
}
int n = nums.length;
int prod = 1;
int result = 0;
int left = 0;
for(int i = 0; i < n; i ++) {
prod *= nums[i];
while(left <= i && prod >= k) {
prod /= nums[left];
left ++;
}
result += i-left+1;
}
return result;
}
博客围绕找出元素乘积小于k的子数组个数展开。因数组长度大,遍历所有子数组组合不可行,且子数组连续不能排序。采用滑动窗口方法,固定右边界,滑动左边界,当元素积大于等于k时移除左元素,计算包含右元素的子数组个数,逐步移动右边界求解。
533

被折叠的 条评论
为什么被折叠?



