来源:力扣(LeetCode)
链接: https://leetcode-cn.com/problems/subarray-product-less-than-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
滑动窗口法: 遇到这种连续,且有一定的满足条件的数组问题时候,滑动窗口法是比较好的方法。定义两个指针,left与right,都是从起始位置开始进行:
- 如果right右移,left到right到总乘积仍然小于k,则right继续右移直到不满足上述条件
- 此时,以left开始,right截止时候到满足次数为 r i g h t − l e f t + 1 right-left+1 right−left+1
- 此时left+1,并将总的乘积除以left位置的元素以保证此时left~right之间的元素乘积满足小于k的要求
- 每次满足要求后,left~right之间的次数都满足 r i g h t − l e f t + 1 right-left+1 right−left+1
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;
}
};
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( 1 ) O(1) O(1)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)