持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第25天,点击查看活动详情
题目描述
给定一个正整数数组 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
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/ZVAVXX
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路分析
- 今天的算法题目是数组类型的题目,题目要求该数组内乘积小于 k 的连续的子数组的个数。这句题意的重点是连续子数组,子数组的个数。
- 分析题目之后,首先可以使用朴素方式求解,使用双重循环,枚举出子数组每一种情况,判断是否符合题目。这种方法直接取出了所有情况,题目只需求解子数组的个数,这种方法的缺点是重复计算比较多。
- 再次分析这个题目,nums 是整整数数组,我们使用滑动窗口的思想来做这个题目,固定子数组区间[i, j]。当 i 增大的时候, 区间的乘积会变小。使用 prod 记录乘积,当 prod < k 的时候,prod 和数组元素累乘。当 prod >= k 的时候,窗口滑动,i 增加, prod 除以 nums[i],动态更新。减少重复计算。实现代码如下,供参考。
通过代码
class Solution {
public int numSubarrayProductLessThanK(int[] nums, int k) {
int ans = 0;
int n = nums.length;
int prod = 1, i = 0;
for (int j = 0; j < n; j++) {
prod *= nums[j];
while (i <= j && prod >= k) {
prod /= nums[i];
i++;
}
ans += j - i + 1;
}
return ans;
}
}
总结
- 上述算法的时间复杂度是O(n),空间复杂度是O(1)
- 坚持算法每日一题,加油!