1343. 大小为 K 且平均值大于等于阈值的子数组数目 Medium
给你一个整数数组 arr 和两个整数 k 和 threshold 。
请你返回长度为 k 且平均值大于等于 threshold 的子数组数目。
示例 1:
输入:arr = [2,2,2,2,5,5,5,8], k = 3, threshold = 4
输出:3
解释:子数组 [2,5,5],[5,5,5] 和 [5,5,8] 的平均值分别为 4,5 和 6 。其他长度为 3 的子数组的平均值都小于 4 (threshold 的值)。
示例 2:
输入:arr = [11,13,17,23,29,31,7,5,2,3], k = 3, threshold = 5
输出:6
解释:前 6 个长度为 3 的子数组平均值都大于 5 。注意平均值不是整数。
解题思路
输入:一个整数数组 arr,以及两个整数 k 和 threshold
输出:返回所有长度为 k 且平均值大于等于 threshold 的子数组数量
本题属于典型的 固定长度滑动窗口类型 问题。
我们可以维护一个大小为 k 的滑动窗口,记录窗口内元素的总和。由于每个子数组的平均值等于窗口总和除以 k,我们可以预先计算一个阈值总和 k * threshold,将问题转化为判断窗口总和是否大于等于该值,从而避免重复使用除法运算。
在遍历数组时,每次窗口右移一位,加入新的元素、移除最左侧的旧元素,更新当前窗口和。若当前窗口和大于等于阈值总和,则说明该子数组满足条件,计数器加一。
遍历结束后返回计数器的值即可。
代码实现
python
class Solution:
def numOfSubarrays(self, arr: List[int], k: int, threshold: int) -> int:
# 初始化窗口内的和(前 k 个元素之和)
window_sum = sum(arr[:k])
# 判断初始窗口的平均值是否大于等于 threshold
# 因为 window_sum / k >= threshold 等价于 window_sum >= k * threshold
count = 1 if window_sum >= k * threshold else 0
# 从第 k 个元素开始滑动窗口(右端进入新元素,左端移除旧元素)
for i in range(k, len(arr)):
# 滑动窗口更新:加上新元素,减去滑出窗口的元素
window_sum += arr[i] - arr[i - k]
# 如果当前窗口平均值 >= threshold,就计数加 1
if window_sum >= k * threshold:
count += 1
return count # 返回满足条件的子数组个数
javascript
const numOfSubarrays = function(arr, k, threshold) {
// 初始化窗口内的和(前 k 个元素之和)
let windowSum = 0;
for (let i = 0; i < k; i++) {
windowSum += arr[i];
}
// 判断初始窗口的平均值是否大于等于 threshold
// 因为 window_sum / k >= threshold 等价于 window_sum >= k * threshold
let count = windowSum >= k * threshold ? 1 : 0;
// 从第 k 个元素开始滑动窗口(右端进入新元素,左端移除旧元素)
for (let i = k; i < arr.length; i++) {
// 滑动窗口更新:加上新元素,减去滑出窗口的元素
windowSum += (arr[i] - arr[i - k]);
// 如果当前窗口平均值 >= threshold,就计数加 1
if (windowSum >= k * threshold) {
count ++;
}
}
// 返回满足条件的子数组个数
return count;
};
复杂度分析
时间复杂度:O(n)
空间复杂度:O(1)