1. 程式人生 > 其它 >LeetCode每日一題——713. 乘積小於 K 的子陣列(滑動視窗)

LeetCode每日一題——713. 乘積小於 K 的子陣列(滑動視窗)

題目描述

給你一個整數陣列 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/