Fixed and Bounded Windows
What is this?
A nurse checks a patient's average heart rate over every rolling 7-day span. She does not re-add seven numbers each morning — she adds today's reading and subtracts the one from eight days ago. That is a fixed window: constant work per day, no matter how long the record.
The second half of this chapter is the harder question the same ward might ask: over how many stretches did the heart rate stay entirely between 60 and 100, touching both limits? The window is no longer a fixed size, and re-scanning each candidate stretch is quadratic. The answer turns out to need only three remembered positions.
add entrant, remove leaver"] B -->|"no — a validity band"| D["Track three positions"] D --> D1["lastBad: last index outside the band"] D --> D2["lastMin: last index equal to minK"] D --> D3["lastMax: last index equal to maxK"] D --> E["count += max(0, min(lastMin, lastMax) - lastBad)"]
💡 Fun fact: Count Subarrays With Fixed Bounds looks like it needs a nested loop and is solved by three integers. A subarray ending at
iis valid exactly when it starts after the last out-of-band element and early enough to include both aminKand amaxK— so counting the qualifying starts is a subtraction. It is an unusually pure example of replacing enumeration with arithmetic on positions.
🔓 The 2 problems in this chapter are free. Sign in with Google or Microsoft to start solving.
The one-line idea: when the window's length is fixed, roll the statistic. When the window is defined by a condition instead, stop thinking about windows and start tracking the last position where each part of the condition was met or broken — the number of valid starts is then a subtraction.
1. The fixed roll
window = sum(nums[:k])
best = window
for i in range(k, len(nums)):
window += nums[i] - nums[i - k] # entrant in, leaver out
best = max(best, window)
Two things worth saying out loud in an interview. First, average and sum rank identically for a fixed k, so compare sums and divide once at the end — it sidesteps floating-point comparison entirely. Second, this works only because a sum can be undone by subtraction; had the problem asked for the window's maximum, this loop would be wrong and you would need a deque.
2. The bounded-extremes count
A subarray [start .. i] is valid when three things hold:
- it contains no element outside
[minK, maxK], - it contains at least one element equal to
minK, - it contains at least one element equal to
maxK.
Walk i forward keeping three positions: lastBad (the most recent index violating rule 1), lastMin and lastMax. A start position is valid exactly when it sits after lastBad and no later than both lastMin and lastMax. The number of such starts is:
count += max(0, min(lastMin, lastMax) - lastBad)
All three are initialised to -1, which makes the arithmetic work from the very first index with no special case.
3. A 30-second worked example
nums = [1, 3, 5, 2, 7, 5], minK = 1, maxK = 5.
i val lastBad lastMin lastMax min(lastMin,lastMax) - lastBad count
0 1 -1 0 -1 min(0,-1) = -1 → -1 - (-1) = 0 0
1 3 -1 0 -1 -1 - (-1) = 0 0
2 5 -1 0 2 min(0,2) = 0 → 0 - (-1) = 1 1
3 2 -1 0 2 0 - (-1) = 1 2
4 7 4 0 2 0 - 4 = -4 → clamped to 0 2
5 5 4 0 5 0 - 4 = -4 → clamped to 0 2
answer = 2
The two valid subarrays are [1,3,5] and [1,3,5,2]. Notice how the 7 at index 4 poisons every start before it, and nothing after index 4 supplies a fresh minK, so the count stops growing. No subarray was ever enumerated.
4. Where you'll actually meet this
- Vital-sign and SLA monitoring. "How many stretches stayed inside the acceptable band?" is rule 1 plus the counting arithmetic above.
- Manufacturing quality control. Statistical process control asks precisely this: count runs that stayed within tolerance while touching both control limits.
- Financial compliance. Detecting periods where a price stayed inside a collar — and the moment it broke out — is the
lastBadreset. - Time-series databases. Moving averages over fixed windows are the base case in every one of them, implemented as a roll for exactly the reason above.
- Audio and sensor processing. Fixed-size frames with rolling energy calculations underpin most real-time signal pipelines.
5. Problems in this chapter
▶ Diet Plan Performance
Score a fixed k-day window of calories against a lower and upper bound, totalling points across all windows. The roll in its plainest form.
Pattern: fixed window, rolling sum. Target: O(n) time, O(1) space.
▶ Count Subarrays With Fixed Bounds
Count subarrays whose minimum is exactly minK and maximum exactly maxK. Three tracked positions and one subtraction per index — no nested loop, and no window in the usual sense.
Pattern: last-position tracking + counting arithmetic. Target: O(n) time, O(1) space.
6. Common pitfalls 🚫
- Recomputing the window sum inside the loop. That is the difference between O(n) and O(nk), and it is easy to write by accident once the statistic is more than one variable.
- Comparing averages as floats. For fixed
k, compare sums and divide at the end. - Forgetting that
lastBadinvalidates everything before it. Every count after an out-of-band element must start strictly later than that index. - Initialising the three positions to
0. They must be-1, or the first index is counted as though a valid start already existed. - Dropping the
max(0, …)clamp. Whenmin(lastMin, lastMax)falls beforelastBad, the subtraction goes negative and silently eats earlier counts. - Special-casing
minK == maxK. It needs none — both positions update on the same element and the arithmetic still holds.
7. Key takeaways
- A fixed window rolls — add the entrant, remove the leaver, O(1) per step.
- Only reversible statistics can roll. Sums yes, maximums no.
- When the window is defined by a condition, track positions rather than contents. Three integers replace an inner loop.
- Valid starts form a range, so counting them is a subtraction rather than an enumeration.
- Initialise boundary positions to
-1and the first-index case handles itself. - Why interviewers like it: the fixed roll is a warm-up; the bounded-extremes problem tests whether you can restate a condition about subarrays as constraints on their start positions, which is a genuinely different way of seeing it.
Order: Diet Plan Performance → Count Subarrays With Fixed Bounds.
Diet Plan Performance
Core idea: Slide a fixed-width window of
kdays across the calorie log, keeping a rolling sum you edit (+entering, −leaving) instead of rebuilding. At every position, classify that window's total against a band: aboveupperis+1, belowloweris-1, inside is0. Sum the verdicts. The whole problem is oneO(n)pass of "roll the sum, score the band."
Problem, rephrased
A dieter logs how many calories they ate each day. You're handed that log plus a fixed review horizon of k days and a target band [lower, upper]. For every consecutive k-day stretch — days 0..k-1, then 1..k, then 2..k+1, and so on — you add up the calories in that stretch and grade it:
- total above
upper→ the dieter "performed well," +1 point - total below
lower→ "performed poorly," −1 point - total inside the band (
lower ≤ T ≤ upper) → "normal," no change
Start at zero points, grade every window, and return the running total. The score can go negative — that's expected, not a bug.
You don't return which windows scored, or the window sums themselves. You return one integer: the net points across all n − k + 1 windows.
Formally (LeetCode 1176): given calories[], window size k, and bounds lower/upper, sum +1/−1/0 over each length-k window's total and return the result.
calories |
k |
lower |
upper |
Output | Why |
|---|---|---|---|---|---|
[1,2,3,4,5] |
1 | 3 | 3 | 0 | 1,2 < 3 → −2; 4,5 > 3 → +2; 3 is in band → net 0 |
[3,2] |
2 | 0 | 1 | 1 | one window 3+2=5 > 1 → +1 |
[6,5,0,0] |
2 | 1 | 5 | 0 | 11>5 (+1), 5 in band (0), 0<1 (−1) → net 0 |
[1,2,3,4,5] |
5 | 16 | 20 | −1 | one window 15 < 16 → −1 |
[10] |
1 | 5 | 8 | 1 | single window 10 > 8 → +1 |
Sign in to continue reading
The rest of this lesson is available with a free account. Signing in with Google or Microsoft is free.
Sign in to read the full lesson