1343. Number of Sub Arrays of Size K and Avg Greater than or Equal to Threshold - Explanation
Description
You are 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: 3Explanation: 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: 6Explanation: The first 6 sub-arrays of size 3 have averages greater than 5. Note that averages are not integers.
Constraints:
1 <= k <= arr.length <= 100,0001 <= arr[i] <= 10,0000 <= threshold <= 10,000
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Sliding Window Technique - Efficiently processing fixed-size subarrays by adding/removing elements at window boundaries
- Prefix Sum - Precomputing cumulative sums to enable O(1) range sum queries
- Array Traversal - Iterating through arrays with multiple pointers to define window boundaries
1. Brute Force
Intuition
For each valid starting position of a subarray of size k, we compute the sum of all elements in that window and check if the average meets the threshold. This approach recalculates the sum from scratch for every window.
Algorithm
- Iterate through all possible starting indices
lfrom0ton - k. - For each window, compute the sum of elements from index
ltol + k - 1. - If
sum / k >= threshold, increment the result counter. - Return the total count.
Time & Space Complexity
- Time complexity:
- Space complexity:
Where is the size of the array and is the size of the sub-array.
2. Prefix Sum
Intuition
Instead of recalculating sums from scratch, we precompute prefix sums. The sum of any subarray from index l to r becomes a simple subtraction: prefix[r+1] - prefix[l]. This trades memory for faster subarray sum queries.
Algorithm
- Build a prefix sum array where
prefix[i]holds the sum of elements from index0toi-1. - For each window of size
k, compute the sum asprefix[r+1] - prefix[l]. - If the average meets the threshold, increment the count.
- Return the total count.
class Solution:
def numOfSubarrays(self, arr: List[int], k: int, threshold: int) -> int:
prefix_sum = [0] * (len(arr) + 1)
for i in range(len(arr)):
prefix_sum[i + 1] += prefix_sum[i] + arr[i]
res = l = 0
for r in range(k - 1, len(arr)):
sum_ = prefix_sum[r + 1] - prefix_sum[l]
if sum_ / k >= threshold:
res += 1
l += 1
return resTime & Space Complexity
- Time complexity:
- Space complexity:
Where is the size of the array and is the size of the sub-array.
3. Sliding Window - I
Intuition
We maintain a running sum of the current window. When the window slides, we add the new element entering from the right and remove the element leaving from the left. This gives constant-time updates per window instead of recalculating from scratch.
Algorithm
- Initialize
curSumwith the sum of the firstk-1elements. - For each starting position
L:- Add the element at position
L + k - 1to complete the window. - Check if the average meets the threshold.
- Remove the element at position
Lbefore moving to the next window.
- Add the element at position
- Return the count of valid subarrays.
Time & Space Complexity
- Time complexity:
- Space complexity: extra space.
Where is the size of the array and is the size of the sub-array.
4. Sliding Window - II
Intuition
A small optimization: instead of dividing the sum by k for each comparison, we multiply the threshold by k once upfront. This converts the average check into a simple sum comparison, avoiding repeated division.
Algorithm
- Multiply
thresholdbykto get the target sum. - Expand the window by adding elements from the right.
- Once the window reaches size
k:- Check if the current sum meets or exceeds the target.
- Shrink the window from the left by removing the oldest element.
- Return the count of valid subarrays.
Time & Space Complexity
- Time complexity:
- Space complexity: extra space.
Where is the size of the array and is the size of the sub-array.
Common Pitfalls
Integer Division Truncation
When computing sum / k in languages like Java, C++, or Go, integer division truncates toward zero. If the sum is 15 and k is 4, 15 / 4 equals 3, not 3.75. This can cause false negatives when the true average meets the threshold but the truncated result does not. Multiplying the threshold by k and comparing sums directly avoids this issue.
Recalculating the Window Sum
A common inefficiency is recalculating the sum for each window from scratch, leading to O(n*k) time complexity. The sliding window technique maintains a running sum, adding the new element and removing the old element in O(1) time per window.
Off-By-One Errors in Window Boundaries
When sliding the window, it is easy to make mistakes with index calculations. Ensure the window always contains exactly k elements. Common errors include starting the right pointer at the wrong index or incorrectly computing when to start shrinking the window from the left.
Sign in to join the discussion