Fixed windows have a constant width. Variable windows grow and shrink to satisfy
a condition — "the longest substring with no repeats," "the shortest subarray summing
to at least target," "count subarrays whose product is below k." Two pointers, left
and right, bound the window.
left = 0
for right in 0..length(nums)-1:
// 1. include nums[right] in the window
add(nums[right])
// 2. shrink from the left while the window is invalid
while windowIsInvalid():
remove(nums[left])
left += 1
// 3. the window [left..right] is now valid — record the answer
best = max(best, right - left + 1)
return best
right always moves forward; left only ever moves forward too. So even though
there's an inner loop, each element is added once and removed once — the total work is
O(n).
The whole problem is in deciding when the window is invalid and what to record:
right
and starting at any index in [left, right] is valid, so add right-left+1.Variable windows that rely on "shrink when the sum is too big" assume non-negative numbers — with negatives, growing the window can decrease the sum, so shrinking logic breaks (you'd reach for prefix sums and a hash map instead). For the problems here, the inputs are chosen so the window technique applies cleanly.