Given an array of integers arr
, an integer k
, and an integer threshold
, your task is to count the number of contiguous subarrays of size k
whose average value is greater than or equal to threshold
.
arr
once per subarray window (i.e., subarrays must be contiguous and non-overlapping).
Example:
Input: arr = [2,1,3,4,1,2,3,2]
, k = 3
, threshold = 3
Output: 3
The problem asks us to count all contiguous subarrays of length k
whose average is at least threshold
.
A straightforward (brute-force) approach would be to check every possible subarray of length k
, compute its average, and count the ones that meet the criterion.
However, this brute-force solution would require us to sum up k
elements for each subarray, leading to a time complexity of O(n*k)
, which is not efficient for large arrays.
To optimize, we observe that each subarray of length k
overlaps heavily with the next one. By using a sliding window technique, we can efficiently compute the sum of each subarray in O(1)
time after the first window by subtracting the element that leaves the window and adding the new element that enters.
We use the sliding window approach to efficiently compute the sum of every subarray of size k
and check if its average meets the threshold.
k
elements of arr
. This sum represents the first window.
k
) is at least threshold
. If it is, increment the count.
Why use window sum instead of average? Since we only care about whether the average is at least threshold
, we can avoid floating-point division by comparing window_sum
directly to threshold * k
.
Let's walk through the example:
arr = [2,1,3,4,1,2,3,2]
, k = 3
, threshold = 3
Oops! This example doesn't have any windows with average ≥ 3. Let's try another example:
arr = [1,4,2,5,6]
, k = 2
, threshold = 4
Only the last window meets the criterion, so the answer is 1.
The key insight for this problem is to use a sliding window to efficiently compute the sum of each subarray of size k
in constant time, rather than recomputing sums from scratch. This reduces the time complexity from O(n*k) to O(n), making the solution suitable for large arrays. By comparing the window sum to threshold * k
, we avoid division and floating-point issues. This approach is elegant, efficient, and easy to implement.
class Solution:
def numOfSubarrays(self, arr, k, threshold):
count = 0
window_sum = sum(arr[:k])
target = threshold * k
if window_sum >= target:
count += 1
for i in range(k, len(arr)):
window_sum += arr[i] - arr[i - k]
if window_sum >= target:
count += 1
return count
class Solution {
public:
int numOfSubarrays(vector<int>& arr, int k, int threshold) {
int count = 0;
int window_sum = 0;
int target = threshold * k;
for (int i = 0; i < k; ++i) {
window_sum += arr[i];
}
if (window_sum >= target) count++;
for (int i = k; i < arr.size(); ++i) {
window_sum += arr[i] - arr[i - k];
if (window_sum >= target) count++;
}
return count;
}
};
class Solution {
public int numOfSubarrays(int[] arr, int k, int threshold) {
int count = 0;
int windowSum = 0;
int target = threshold * k;
for (int i = 0; i < k; i++) {
windowSum += arr[i];
}
if (windowSum >= target) count++;
for (int i = k; i < arr.length; i++) {
windowSum += arr[i] - arr[i - k];
if (windowSum >= target) count++;
}
return count;
}
}
var numOfSubarrays = function(arr, k, threshold) {
let count = 0;
let windowSum = 0;
let target = threshold * k;
for (let i = 0; i < k; i++) {
windowSum += arr[i];
}
if (windowSum >= target) count++;
for (let i = k; i < arr.length; i++) {
windowSum += arr[i] - arr[i - k];
if (windowSum >= target) count++;
}
return count;
};