本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
713. 乘积小于k
来源:力扣(LeetCode)
链接: leetcode-cn.com/problems/su…
给你一个整数数组 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 * 1041 <= nums[i] <= 10000 <= k <= 106
解法
滑动窗口法: 遇到这种连续,且有一定的满足条件的数组问题时候,滑动窗口法是比较好的方法。定义两个指针,left与right,都是从起始位置开始进行:
- 如果right右移,left到right到总乘积仍然小于k,则right继续右移直到不满足上述条件
- 此时,以left开始,right截止时候到满足次数为
- 此时left+1,并将总的乘积除以left位置的元素以保证此时left~right之间的元素乘积满足小于k的要求
- 每次满足要求后,left~right之间的次数都满足
代码实现
python实现
class Solution:
def numSubarrayProductLessThanK(self, nums: List[int], k: int) -> int:
# 滑动窗口
res, left, ji = 0, 0, 1
for right in range(0, len(nums)):
ji *= nums[right]
# 当积超出k的时候ji/nums[left],然后left右移
while ji >= k and left <= right:
ji /= nums[left]
left += 1
# left->right的情况都符合,并且包含left自己做子数组的时候
# 每次右指针位移到一个新位置,应该加上 x 种数组组合:
# nums[right]
# nums[right-1], nums[right]
# nums[right-2], nums[right-1], nums[right]
# nums[left], ......, nums[right-2], nums[right-1], nums[right]
# 共有 right - left + 1 种
res += right - left + 1
return res
c++实现
class Solution {
public:
int numSubarrayProductLessThanK(vector<int>& nums, int k) {
int n = nums.size();
if(k==0)
{
return 0;
}
int l = 0;
int r = 0;
int prod = 1;
int count = 0;
while(r < n)
{
prod *= nums[r];
while( prod >= k && l <= r)
{
prod = prod / nums[l];
l += 1;
}
count += r - l + 1;
r++;
}
return count;
}
};
复杂度分析
- 时间复杂度:
- 空间复杂度: