Subarray Product Less Than K
Question:
思路
这道题比较直观的解法就是两个for loop
第一个大loop iterate throught 所有的nums,
里面的loop iterate 一遍所有后续的num并且直接算乘积.
loop 里每做一次乘积, 就可以判断一次< k, 可以直接count
接着等乘积 > k, 就可以break, 从下一个num开始再iterate。
这个方法很直观, 但是效率比较慢 大概是O(N)
解这个题用Slinding Window的话就比较快,
sliding window.
define一个product 用来一直做乘积
right 一直不停的乘以每一个num, 并且每一次乘right num, 都可以进行一次continous subarray的数量增加. 直到product > k, 我们就该缩减左侧的window了。 并且减小乘积. 然后再增加我们最后答案的统计.
举个直观的例子,因为只看代码容易理解不了.
I was SO close to solving this via sliding window, but couldn’t come up with ans += right - left + 1…
For those who are confused, let’s use the example nums = [10,5,2,6]:
If we start at the 0th index, [10], the number of intervals is obviously 1.
If we move to the 1st index, the window is now [10,5]. The new intervals created are [5] and [10,5], so we add 2.
Now, expand the window to the 2nd index: [10,5,2]. The new intervals are [2], [5,2], and [10,5,2], so we add 3.
The pattern should be obvious by now; we add right - left + 1 to the output variable every loop!
同理, 当product > k 的时候, product /=nums[left++]
此时既然能运行到product > k, 就说明right 还有一个num, 还没有适配所有的可能结果<k的乘积.
所以我们要缩减left 把window变小, 从而寻找此时可能和num[right] 形成的subarray.
那么同理这个时候我们还是做 result += right - left +1;
假设按照上面的例子继续写. assume nums[4] = x,
现在的window变成了[5,2,6,x]
那么x就是最新加进window里的. 新的interval 是[x] [6,x] [2,6,x] [5,2,6,x]
so we add 4.
就是这个规律
class Solution {
public int numSubarrayProductLessThanK(int[] nums, int k) {
if(k <= 1) { return 0;}
int result = 0;
double product = 1;
int left = 0;
for (int right = 0; right < nums.length; right++) {
product *= nums[right];
while (product >= k && left < nums.length)
product /= nums[left++];
// since the product of all numbers from left to right is less than the target therefore,
// all subarrays from left to right will have a product less than the target too; to avoid
// duplicates, we will start with a subarray containing only arr[right] and then extend it
result += right-left + 1;
}
return result;
}
}