ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LeetCode每日一题——713. 乘积小于 K 的子数组(滑动窗口)

2022-05-05 13:03:34  阅读:159  来源: 互联网

标签:10 cnt return 乘积 nums int 713 deque LeetCode


题目描述

给你一个整数数组 nums 和一个整数 k ,请你返回子数组内所有元素的乘积严格小于 k 的连续子数组的数目。
 

示例 1:

输入:nums = [10,5,2,6], k = 100
输出:8
解释:8 个乘积小于 100 的子数组分别为:[10]、[5]、[2],、[6]、[10,5]、[5,2]、[2,6]、[5,2,6]。
需要注意的是 [10,5,2] 并不是乘积小于 100 的子数组。
示例 2:

输入:nums = [1,2,3], k = 0
输出:0
 

提示: 

1 <= nums.length <= 3 * 104
1 <= nums[i] <= 1000
0 <= k <= 106

暴力——二分+前缀和

 1 import java.util.*;
 2 import java.math.*;
 3 
 4 class Solution {
 5 
 6     int N = 30000 + 10;
 7 
 8     private BigDecimal[] pre = new BigDecimal[N];
 9 
10     public int numSubarrayProductLessThanK(int[] nums, int k) {
11         // 时间复杂度: O(nlogn)
12         // 性质:前缀乘积递增,可以用二分
13         // 暴力+前缀和
14         if (k == 0) {
15             return 0;
16         }
17         int n = nums.length;
18         pre[0] = BigDecimal.ONE;
19         for (int i = 1; i <= n; i++) {
20             pre[i] = pre[i - 1].multiply(new BigDecimal(String.valueOf(nums[i - 1])));
21         }
22 
23         int cnt = 0;
24         // 枚举每一个左边界
25         for (int i = 1; i <= n; i++) {
26             // 二分
27             int left = i;
28             int right = n;
29             while (left <= right) {
30                 int mid = (left + right) >> 1;
31                 if (check(i, mid, k)) {
32                     left = mid + 1;
33                 } else {
34                     right = mid - 1;
35                 }
36             }
37             // 有可能一个都不满足的情况
38             if (right >= i) {
39                 cnt += (right - i + 1);
40             }
41         }
42         return cnt;
43     }
44 
45     public boolean check(int left, int right, int k) {
46         int result = pre[right].divide(pre[left - 1]).compareTo(new BigDecimal(String.valueOf(k)));
47         return result < 0 ? true : false;
48     }
49 }

优化——滑动窗口

 1 class Solution {
 2     public int numSubarrayProductLessThanK(int[] nums, int k) {
 3         if (k == 0 || k == 1) {
 4             return 0;
 5         }
 6         int n = nums.length;
 7         // 滑动窗口
 8         int curMutil = 1;
 9         int cnt = 0;
10         Deque<Integer> deque = new LinkedList<>();
11         for (int i = 1; i <= n; i++) {
12             while (deque.size() > 0 && curMutil * nums[i - 1] >= k) {
13                 curMutil /= nums[deque.getFirst() - 1];
14                 deque.pollFirst();
15             }
16             if (curMutil * nums[i - 1] < k) {
17                 curMutil *= nums[i - 1];
18                 deque.offerLast(i);
19                 // 每次多一个区间的长度个数
20                 cnt += (deque.getLast() - deque.getFirst() + 1);
21             }
22         }
23 
24         return cnt;
25     }
26 }

力扣链接:https://leetcode.cn/problems/subarray-product-less-than-k/

标签:10,cnt,return,乘积,nums,int,713,deque,LeetCode
来源: https://www.cnblogs.com/pengsay/p/16224319.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有