Given an array of integers arr
and two integers k
and threshold
, return the number of sub-arrays of size k
and average greater than or equal to threshold
.
Example 1:
Input: arr = [2,2,2,2,5,5,5,8], k = 3, threshold = 4 Output: 3 Explanation: Sub-arrays [2,5,5],[5,5,5] and [5,5,8] have averages 4, 5 and 6 respectively. All other sub-arrays of size 3 have averages less than 4 (the threshold).
Example 2:
Input: arr = [11,13,17,23,29,31,7,5,2,3], k = 3, threshold = 5 Output: 6 Explanation: The first 6 sub-arrays of size 3 have averages greater than 5. Note that averages are not integers.
Constraints:
1 <= arr.length <= 105
1 <= arr[i] <= 104
1 <= k <= arr.length
0 <= threshold <= 104
This problem asks to find the number of sub-arrays of size k
whose average is greater than or equal to threshold
. A straightforward approach involves iterating through all possible sub-arrays of size k
and checking their averages. However, this would lead to a time complexity of O(n*k), where n is the length of the input array. A more efficient solution uses the sliding window technique to achieve linear time complexity.
Sliding Window Technique:
The core idea is to maintain a window of size k
that slides across the input array. Instead of recalculating the sum of each sub-array from scratch, we update the sum incrementally as the window moves.
Initialization: Calculate the sum of the first k
elements of the array. This forms the initial sliding window. Check if the average of this window (sum/k) meets the threshold criteria. If it does, increment the counter of qualifying sub-arrays.
Sliding the Window: For each subsequent step, we move the window one element to the right. This is done by subtracting the leftmost element of the current window from the sum and adding the newly included rightmost element. This maintains the sum of the current window efficiently.
Threshold Check: After each window update, check if the average of the current window (sum/k) meets the threshold. If it does, increment the counter.
Return Value: The final counter represents the total number of sub-arrays of size k
that satisfy the average condition.
Time Complexity Analysis:
The algorithm iterates through the array once using a single loop. The operations within the loop (addition, subtraction, comparison) take constant time. Therefore, the overall time complexity is O(n), where n is the length of the input array arr
.
Space Complexity Analysis:
The algorithm uses a few variables to store the sum, counter, and window size. The space used is constant and does not depend on the input size. Thus, the space complexity is O(1).
The following code snippets implement the sliding window approach in several programming languages. They all follow the same logic:
Python:
class Solution:
def numOfSubarrays(self, arr: List[int], k: int, threshold: int) -> int:
threshold *= k # Optimize: Multiply threshold by k for direct comparison
window_sum = sum(arr[:k])
count = 1 if window_sum >= threshold else 0 # Initialize count
for i in range(k, len(arr)):
window_sum += arr[i] - arr[i - k] # Efficiently update window sum
count += 1 if window_sum >= threshold else 0
return count
Java:
class Solution {
public int numOfSubarrays(int[] arr, int k, int threshold) {
int thresholdK = k * threshold; // Optimize: Pre-compute threshold * k
int windowSum = 0;
for (int i = 0; i < k; i++) {
windowSum += arr[i];
}
int count = (windowSum >= thresholdK) ? 1 : 0;
for (int i = k; i < arr.length; i++) {
windowSum += arr[i] - arr[i - k];
count += (windowSum >= thresholdK) ? 1 : 0;
}
return count;
}
}
C++:
class Solution {
public:
int numOfSubarrays(vector<int>& arr, int k, int threshold) {
int thresholdK = k * threshold;
int windowSum = accumulate(arr.begin(), arr.begin() + k, 0);
int count = (windowSum >= thresholdK);
for (int i = k; i < arr.size(); i++) {
windowSum += arr[i] - arr[i - k];
count += (windowSum >= thresholdK);
}
return count;
}
};
Go:
func numOfSubarrays(arr []int, k int, threshold int) int {
threshold *= k
windowSum := 0
for i := 0; i < k; i++ {
windowSum += arr[i]
}
count := 0
if windowSum >= threshold {
count++
}
for i := k; i < len(arr); i++ {
windowSum += arr[i] - arr[i-k]
if windowSum >= threshold {
count++
}
}
return count
}
Javascript:
/**
* @param {number[]} arr
* @param {number} k
* @param {number} threshold
* @return {number}
*/
var numOfSubarrays = function(arr, k, threshold) {
let thresholdK = k * threshold;
let windowSum = arr.slice(0, k).reduce((a, b) => a + b, 0);
let count = (windowSum >= thresholdK) ? 1 : 0;
for(let i = k; i < arr.length; i++){
windowSum += arr[i] - arr[i - k];
count += (windowSum >= thresholdK) ? 1 : 0;
}
return count;
};
These code snippets demonstrate a concise and efficient solution to the problem using the sliding window technique. The optimizations (pre-computing threshold * k
) further enhance the performance. All implementations achieve a time complexity of O(n) and a space complexity of O(1).