leetcode713. 乘积小于 K 的子数组

leetcode713. 乘积小于 K 的子数组,第1张

给你一个整数数组 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

解题思路:
滑动窗口 O(n) O(1)

  1. 滑窗口维护一个所有元素乘积小于k的窗口,如果乘积大于等于k,那么移动左边界直到窗口的乘积值小于k。那么该窗口的长度就是以右边界j为结尾的连续子树组的最大长度。
  2. 根据1那没就需要遍历以每个元素为结尾的窗口长度。并进行累计求和。

为什么不按照每个元素为起点求长度?
如果是这样时间复杂度就变成了n平方了,滑动窗口也就没有了意义。滑动窗口保证了,后面元素的起点一定大于前面元素的起点。dp[i] < dp[i+1] = dp[i] * nums[i+1] dp[i] < k 但是dp[i + 1]不一定小于k 但是i+1为结尾的左边界一定大于以i为结尾对应的左边界。
代码如下:

class Solution {
public:
    int numSubarrayProductLessThanK(vector<int>& nums, int k) {
        int res = 0;
        int i = 0, count = 1;
        for (int j = 0; j < nums.size(); ++j) {
            count *= nums[j];
            while (count >= k && i <= j) {
                count = count/nums[i];
                i++;
            }
            res  = res + j - i + 1;
        }
        return res;
    }
};```

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/875342.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-13
下一篇2022-05-13

发表评论

登录后才能评论

评论列表(0条)

    保存