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:

  1. Input: nums = [10, 5, 2, 6], k = 100
  2. Output: 8
  3. Explanation: The 8 subarrays that have product less than 100 are: [10], [5], [2], [6], [10, 5], [5, 2], [2, 6], [5, 2, 6].
  4. 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.

Idea 1. Brute force, any subarray nums[i..j] can be represented by a given pair of integers 0 <= i <= j < nums.length.

Time complexity: O(n2)

Space complexity: O(1)

  1. class Solution {
  2. public int numSubarrayProductLessThanK(int[] nums, int k) {
  3. int count = 0;
  4. for(int i = 0; i < nums.length; ++i) {
  5. int product = 1;
  6. for(int j = i; j < nums.length; ++j) {
  7. product *= nums[j];
  8. if(product < k) {
  9. ++count;
  10. }
  11. else break;
  12. }
  13. }
  14. return count;
  15. }
  16. }

Idea 2. Binary search. Taking advantage:

  1. log(x*y) = log(x) + log(y)

2. positive numbers mean monoto increasing for subarray product(or log subarray sum), the prefix product/sum is sorted

reducing subarry product problem to subarray sum problem. For each index i, find the rightmost index j such that prefix[j] - nums[i-1] < Math.log(k). Note the comparison for double, reduce log(k) by 1e-9, to avoid searching the wrong half.

Take nums= {10,3,3,7,2,9,7,4,7,2,8,6,5,1,5},  k = 30 for example,

when searching the subarray {6, 5, 1, 5},  6* 5 * 1 == 30, if not adding 1e-9, the search will move to {5} because of doble comparison, hence make logK slightly smaller, if the product is equal to k, move to the lower half.

Time complexity: O(nlogn)

Space complexity: O(n)

  1. class Solution {
  2. int findMaxIndex(double[] prefix, int left, int right, int k) {
  3. double logK = Math.log(k);
  4. int i = left, j = right;
  5. while(i < j) {
  6. int mid = i + (j - i) / 2;
  7. if(prefix[mid] - prefix[left-1] < logK - 1e-9) i = mid + 1;
  8. else j = mid;
  9. }
  10. return i;
  11. }
  12.  
  13. public int numSubarrayProductLessThanK(int[] nums, int k) {
  14. int count = 0;
  15.  
  16. double[] prefix = new double[nums.length + 1];
  17. for(int i = 1; i < prefix.length; ++i) {
  18. prefix[i] = prefix[i-1] + Math.log(nums[i-1]);
  19. }
  20.  
  21. for(int i = 1; i < prefix.length; ++i) {
  22. int maxIndex = findMaxIndex(prefix, i, prefix.length, k);
  23. count += maxIndex - i;
  24. }
  25. return count;
  26. }
  27. }

Idea 3. Slicing widnow. Keeping a max-product-windown less than k. Since the elements in the array is positive, the subarray product is a monotone increasing fuction, so we use a sliding window.

Time complexity: O(n)

Space complexity: O(1)

3.a Fixed the left point of a subarray, for each left, find the largest right so that the product of the subarray nums[left] + nums[left+1] + ... + nums[right-1] is less than k. Hence the product of each subarray starting at left and ending at rightEnd (left <= rightEnd < right) is less than k, there are right - left such subarrays. For every left, we update right and prod to maintain the invariant.

  Starting with index left ( left = 0), find the first largest right so that the product * nums[right] is larger than k, add right - left to the count.

  Shifting the window by moving left to the right by element, update product (product = product/nums[left]), the new subarry will start with index left = left + 1,

      if the product*nums[right] is still larger than k, there are right - left subarrys with product less than k; Note: if right == left, it's empty array, no need to update       product, product should remain as 1, it means nums[right] > k, we need to move right forward to maintain the invariant left <= right.

  otherwise, expand right until product * nums[right] > k, continue the above process until left reaches the end of the array.

Take nums = [10, 5, 2, 100, 6], k = 100 for example,

left = 0, right = 2, product = 100, [10, 5, 2] , there are 2 (right - left) subarrays starting at 0 with product less than 100: [10], [10, 5]

left moving forward, left = 1, product = 100/nums[0] = 10, continue expand right until product = 1000 >= k, right = 3, [5, 2, 100], 2 (right - left) subarrays starting with 5: [5], [5, 2]

left moving forward, left = 2, product = 1000/nums[1] = 200, since product is already larger than k, no need to expand right, keep right= 3,  1 (right - left) subarray starting with 2: [2]

left moving forward, left = 3, right = 3, since left < right, as we define right as the excluded boundary, there is no subarry in the range (right - left) = 0, right is not in the product, we need to move right, right = 4

left moving forward, left = 4, product = 1, 1 * 6 < 100, expanding right = 5, 1 subarray starting with 6, [6]

(10)

(10, 5, 2)

(5, 2, 100)

(2, 100)

(100)

(6)

  1. class Solution {
  2. public int numSubarrayProductLessThanK(int[] nums, int k) {
  3. int count = 0;
  4. int product = 1;
  5. for(int left = 0, right = 0; left < nums.length; ++left) {
  6. for(;right < nums.length && product * nums[right] < k; ++right) {
  7. product *= nums[right];
  8. }
  9.  
  10. count += right - left;
  11. if(left < right) {
  12. product = product/nums[left];
  13. }
  14. else {
  15. ++right;
  16. }
  17. }
  18. return count;
  19. }
  20. }

3.b Fix the right point, for each right point, find the smallest left such that the product is less than k.

Shifting the window by adding a new element on the right,

  if the product is less than k, then all the subarray nums[left...right] satisfy the requrement, there are right - left + 1 such subarrays ending at index right;

  otherwise, shrinking the subarray by moving left index to the right until the subarray product less than k; Note if nums[right] >= k, left will move one step before right, the arry ending at right is empty with right - left + 1 = 0.

(10)

(10, 5)

(5, 2)

(100) right = left + 1, count = 0

(6)

  1. class Solution {
  2. public int numSubarrayProductLessThanK(int[] nums, int k) {
  3. int count = 0;
  4. int product = 1;
  5. for(int left = 0, right = 0; right < nums.length; ++right) {
  6. product *= nums[right];
  7. while(left <= right && product >= k) {
  8. product /= nums[left];
  9. ++left;
  10. }
  11. count += right - left + 1;
  12. }
  13. return count;
  14. }
  15. }

Subarray Product Less Than K LT713的更多相关文章

  1. [LeetCode] Subarray Product Less Than K 子数组乘积小于K

    Your are given an array of positive integers nums. Count and print the number of (contiguous) subarr ...

  2. [Swift]LeetCode713. 乘积小于K的子数组 | Subarray Product Less Than K

    Your are given an array of positive integers nums. Count and print the number of (contiguous) subarr ...

  3. 713. Subarray Product Less Than K

    Your are given an array of positive integers nums. Count and print the number of (contiguous) subarr ...

  4. LeetCode Subarray Product Less Than K

    原题链接在这里:https://leetcode.com/problems/subarray-product-less-than-k/description/ 题目: Your are given a ...

  5. Subarray Product Less Than K

    Your are given an array of positive integers nums. Count and print the number of (contiguous) subarr ...

  6. leetcode713 Subarray Product Less Than K

    """ Your are given an array of positive integers nums. Count and print the number of ...

  7. 【LeetCode】713. Subarray Product Less Than K 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/subarray ...

  8. [leetcode] 713. Subarray Product Less Than K

    题目 Given an array of integers nums and an integer k, return the number of contiguous subarrays where ...

  9. LeetCode Subarray Product Less Than K 题解 双指针+单调性

    题意 给定一个正整数数组和K,数有多少个连续子数组满足: 数组中所有的元素的积小于K. 思路 依旧是双指针的思路 我们首先固定右指针r. 现在子数组的最右边的元素是nums[r]. 我们让这个子数组尽 ...

随机推荐

  1. html实现导航栏效果

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. cakePHP 分页栏

    <div class="page"><?php if ($total > 1) echo $this->element('page_list', ar ...

  3. windows上java中文乱码-指定字符集 -Dfile.encoding=UTF-8

    jvm启动中增加参数: -Dfile.encoding=UTF-8 重启即可.

  4. 使用SpirngMvc拦截器实现对登陆用户的身份验证

    登陆成功则按returnUrl进行跳转,即跳转到登陆之前的页面,否则跳转到登陆页面,返回登陆错误信息. 1.SpringMVC.xml <!-- 映射器 --> <bean clas ...

  5. Oracle 入门

    一.安装Oracle 11g 服务端 服务端安装教程:https://jingyan.baidu.com/article/363872eccfb9266e4aa16f5d.html 二.安装客户端 客 ...

  6. web前端开发浏览器兼容性处理大全

    1.居中问题 div里的内容,IE默认为居中,而FF默认为左对齐,可以尝试增加代码margin: 0 auto; 2.高度问题 两上下排列或嵌套的div,上面的div设置高度(height),如果di ...

  7. cloudera cdh5.13.0 vmware 快速安装

    1. 从官网上载VMWARE VM快速安装包 https://www.cloudera.com/downloads/quickstart_vms/5-12.html 2. 下载后的安装包,解压之后得到 ...

  8. 连接SQL常见问题

    HTTP Status 500 – Internal Server Error Type Exception Report Message Request processing failed; nes ...

  9. nodemcu生成LUA版本固件

    构建自己的固件地址 https://nodemcu-build.com/

  10. ngular ionic select ng-options 默认选择第一个值的写法

    1. html <select ng-model="selectOrderState" style="border:none;left:0" ng-opt ...