
题目描述
给你一个整数数组 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
解法
方法一:双指针
我们可以用双指针维护一个滑动窗口,窗口内所有元素的乘积小于 \(k\)。
定义两个指针 \(l\) 和 \(r\) 分别指向滑动窗口的左右边界,初始时 \(l = r = 0\)。我们用一个变量 \(p\) 记录窗口内所有元素的乘积,初始时 \(p = 1\)。
每次,我们将 \(r\) 右移一位,将 \(r\) 指向的元素 \(x\) 加入窗口,更新 \(p = p \times x\)。然后,如果 \(p \geq k\),我们循环地将 \(l\) 右移一位,并更新 \(p = p \div \text{nums}[l]\),直到 \(p < k\) 或者 \(l \gt r\) 为止。这样,以 \(r\) 结尾的、乘积小于 \(k\) 的连续子数组的个数即为 \(r - l + 1\)。然后我们将答案加上这个数量,并继续移动 \(r\),直到 \(r\) 到达数组的末尾。
时间复杂度 \(O(n)\),其中 \(n\) 为数组的长度。空间复杂度 \(O(1)\)。
| class Solution:
def numSubarrayProductLessThanK(self, nums: List[int], k: int) -> int:
ans = l = 0
p = 1
for r, x in enumerate(nums):
p *= x
while l <= r and p >= k:
p //= nums[l]
l += 1
ans += r - l + 1
return ans
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | class Solution {
public int numSubarrayProductLessThanK(int[] nums, int k) {
int ans = 0, l = 0;
int p = 1;
for (int r = 0; r < nums.length; ++r) {
p *= nums[r];
while (l <= r && p >= k) {
p /= nums[l++];
}
ans += r - l + 1;
}
return ans;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | class Solution {
public:
int numSubarrayProductLessThanK(vector<int>& nums, int k) {
int ans = 0, l = 0;
int p = 1;
for (int r = 0; r < nums.size(); ++r) {
p *= nums[r];
while (l <= r && p >= k) {
p /= nums[l++];
}
ans += r - l + 1;
}
return ans;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12 | func numSubarrayProductLessThanK(nums []int, k int) (ans int) {
l, p := 0, 1
for r, x := range nums {
p *= x
for l <= r && p >= k {
p /= nums[l]
l++
}
ans += r - l + 1
}
return
}
|
1
2
3
4
5
6
7
8
9
10
11
12 | function numSubarrayProductLessThanK(nums: number[], k: number): number {
const n = nums.length;
let [ans, l, p] = [0, 0, 1];
for (let r = 0; r < n; ++r) {
p *= nums[r];
while (l <= r && p >= k) {
p /= nums[l++];
}
ans += r - l + 1;
}
return ans;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | impl Solution {
pub fn num_subarray_product_less_than_k(nums: Vec<i32>, k: i32) -> i32 {
let mut ans = 0;
let mut l = 0;
let mut p = 1;
for (r, &x) in nums.iter().enumerate() {
p *= x;
while l <= r && p >= k {
p /= nums[l];
l += 1;
}
ans += (r - l + 1) as i32;
}
ans
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | /**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var numSubarrayProductLessThanK = function (nums, k) {
const n = nums.length;
let [ans, l, p] = [0, 0, 1];
for (let r = 0; r < n; ++r) {
p *= nums[r];
while (l <= r && p >= k) {
p /= nums[l++];
}
ans += r - l + 1;
}
return ans;
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | class Solution {
fun numSubarrayProductLessThanK(nums: IntArray, k: Int): Int {
var ans = 0
var l = 0
var p = 1
for (r in nums.indices) {
p *= nums[r]
while (l <= r && p >= k) {
p /= nums[l]
l++
}
ans += r - l + 1
}
return ans
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | public class Solution {
public int NumSubarrayProductLessThanK(int[] nums, int k) {
int ans = 0, l = 0;
int p = 1;
for (int r = 0; r < nums.Length; ++r) {
p *= nums[r];
while (l <= r && p >= k) {
p /= nums[l++];
}
ans += r - l + 1;
}
return ans;
}
}
|