DSA sheet · Arrays · Sliding Window pattern

Minimum Size Subarray Sum

The teacher calls this the start of the sliding window section after finishing two pointers. It's a medium problem, and it's the classic "shortest valid window" question. She first writes a brute force (two loops with an early break), explains why the answer must start at "infinity" and why we must return 0 when nothing works, then picks sliding window from her four array patterns. Her picture for sliding window is a leech: it stretches its front forward, then pulls its back in.

Why it matters: "shortest subarray that reaches a target" is the mirror image of "longest subarray that stays within a limit". The only real difference is where you record the answer, and this problem teaches that.

Every part below follows the same order:
① the question in simple words → ② what the constraints tell us → ③ intuition → ④ building the logic from examples → ⑤ approach steps → ⑥ code → ⑦ code line by line → ⑧ dry run → ⑨ complexity & remember

Part 0 · Before starting

What is a subarray?

A subarray is a piece of the array whose elements sit next to each other (contiguous). Choose a start index and an end index and take everything in between, with no skipping. (In strings this is called a substring.) Its length is end − start + 1.

index012345
nums231243[1, 2, 4] is a subarray, length 3
nums231243[2, 1] is not (3 is skipped)

The brute force over all windows, and why it repeats work

Two loops can check every subarray: one fixes the start, the other walks the end forward. There are n·(n+1)/2 subarrays, so this is O(n²). The waste: after checking [2, 3, 1, 2], the next start begins again with [3], re-adding 3, 1, 2 that we had already added. Sliding window keeps the running sum and only fixes the edges.

The window [left..right]: expand and shrink

A window is the current subarray, marked by two pointers: left (first index) and right (last index). We keep its sum in a variable so we never re-add it.

The teacher's picture: a leech walking. It stretches its front end forward (that's right, the expansion), then pulls its back end up (that's left, the shrinking), and repeats. Both ends only ever move forward. When to expand and when to shrink depends on the question.

Fixed-size vs variable-size windows

Fixed-size windowVariable-size window
question looks like"every subarray of size k…""longest / shortest / how many subarrays such that…"
how it movesadd the new right element; once the size passes k, remove the element k steps backgrow with right; shrink with left depending on the rule
this problem?no, we're looking for the sizeyes

Longest vs shortest vs count

kindshrink when…record the answer…
longest validthe window becomes invalidafter shrinking: best = max(best, right − left + 1)
shortest valid (this problem)the window is valid (try to make it shorter)inside the shrinking loop, before each shrink: best = min(best, right − left + 1)
count of validthe window becomes invalidafter shrinking: count += right − left + 1 (every valid subarray ending at right)

Another trick you'll meet later: "exactly K" = atMost(K) − atMost(K − 1). Not needed here.

Why sliding window needs positive numbers

Shrinking only makes sense if the rule is monotonic: adding an element must always push the sum up, and removing one must always push it down. With all numbers positive (here every nums[i] ≥ 1), that's guaranteed. If negatives were allowed, adding could lower the sum and removing could raise it, so the window could stop too early and miss answers. (That's why "Subarray Sum Equals K", which allows negatives, uses prefix sums instead.)

Other tools in this pattern (not needed here)

The teacher's 4 array patterns

patternwhen it fits
Two pointersonly two particular points matter, and we compute something from just those two
Sliding windowtwo points and everything in between matter
Prefix summany queries like "sum from index a to index b?"
Kadane'smaximum sum when numbers can be negative

Part A · Brute force: every start, stop at the first valid end

LeetCode 209

1The question in simple words

You get an array of positive integers nums and a positive integer target. Among all subarrays whose sum is greater than or equal to target, return the smallest length. If no subarray reaches target, return 0.

index012345
nums231243target = 7 → answer 2 ([4, 3], sum 7)

Many subarrays reach 7 ([2,3,1,2] = 8, [3,1,2,4] = 10, [1,2,4] = 7, …). We don't want all of them, only the length of the shortest one.

2What the constraints tell us

3Intuition: try every start, extend until it's enough

Fix a starting index i. Move a second pointer j from i forward, adding each number to a running sum. As soon as the sum reaches target, we have the shortest valid subarray that starts at i. Record its length and move on to the next start.

4Building the logic from the example

Start at index 0 (value 2), target 7

jsubarraysum≥ 7?
0[2]2no
1[2,3]5no
2[2,3,1]6no
3[2,3,1,2]8yes → length 3 − 0 + 1 = 4

Why break as soon as it's valid

[2,3,1,2,4] also has sum ≥ 7, and so does [2,3,1,2,4,3]. They're valid, but they're longer, and we want the minimum length. Going further from the same start can only give longer subarrays, so the extra work is useless → break.

Doubt 1: is breaking also safe because of positive numbers?
→ It's safe even without that. From a fixed start, the first j that works gives the shortest length for that start. Anything later is longer. (Positivity is what we need for the sliding window later.)

The length: j − i + 1

Think of i as the left pointer and j as the right pointer. The number of elements from i to j is j − i + 1. Here 3 − 0 + 1 = 4.

Keeping the minimum, and why it starts at "infinity"

We keep an answer variable and update it with ans = min(ans, length). What should ans start as?

The other starts

The case she almost forgot: no valid subarray → 0

Halfway through, the teacher realises something is missing. Suppose the whole array adds up to only 15 (2+3+1+2+4+3) but target is 20. No subarray can reach it, so ans is never updated and is still infinity. We can't return infinity. The question says to return 0 in that case.

The final checkreturn 0 if ans == float('inf') else ans — "still infinity" means "never found a valid subarray".

5Approach steps

  1. ans = infinity.
  2. For each start i: total = 0 (fresh sum for this start).
  3. For j from i to n − 1: add nums[j].
  4. If total ≥ target: ans = min(ans, j − i + 1) and break.
  5. After both loops: return 0 if ans is still infinity, else ans.

6Code (Python)

Brute force: O(n²), TLE for n = 10⁵
class Solution:
    def minSubArrayLen(self, target, nums):
        n = len(nums)
        ans = float('inf')                  # "nothing found yet"
        for i in range(n):                  # start of the subarray
            total = 0                       # fresh sum for this start
            for j in range(i, n):           # end of the subarray
                total += nums[j]
                if total >= target:         # first valid end for this start
                    ans = min(ans, j - i + 1)
                    break                   # longer ones can't be better
        return 0 if ans == float('inf') else ans

7Code line by line

linewhat it means
ans = float('inf')Start bigger than any possible length, so the first real length replaces it. Starting at 0 would break min.
for i in range(n):Every index gets a turn as the start.
total = 0Reset the sum for the new start. It must be inside the outer loop so the old start's sum doesn't leak in.
for j in range(i, n): total += nums[j]Extend the subarray to the right by one element. Now total = sum(nums[i..j]).
if total >= target:"Greater than or equal". A sum exactly equal to target counts.
ans = min(ans, j - i + 1)Length of this subarray, keep it if it's the shortest so far.
breakFrom this start, any further end only makes it longer.
return 0 if ans == float('inf') else ansNo valid subarray anywhere → 0. Otherwise the shortest length.

8Dry run (hand table)

nums = [2, 3, 1, 2, 4, 3], target = 7.

start irunning sums as j movesfirst valid endlengthans after
02, 5, 6, 8 ✓j = 344
13, 4, 6, 10 ✓j = 444
21, 3, 7 ✓j = 433
32, 6, 9 ✓j = 533
44, 7 ✓j = 522
53 (array ends)none–2

Final answer: 2 ✓ ([4, 3]).

9Complexity & remember

Remember the brute forceFor each start: fresh sum, extend right, at the first sum ≥ target record j − i + 1 and break. Start ans at infinity, return 0 if it never changed.

Part B · Optimal: expand until valid, shrink while still valid

LeetCode 209

1The question again, with the new goal

Same question. The goal now is O(n): one pass where left never goes back to restart.

2Choosing the pattern

3Intuition: the leech

left and right start at 0, and the window sum starts at 0.

4Building the logic from examples

First, the expansion on [2, 3, 1, 2, 4, 3], target 7

right = 0: sum 2, not enough. right = 1: sum 5. right = 2: sum 6. Still below 7, so nothing to record and no reason to shrink. Just keep moving right (the for loop does this for us).

right = 3: sum 8 ≥ 7. Valid! Length right − left + 1 = 3 − 0 + 1 = 4. We don't know yet if it's the minimum, but it's a valid length, so ans = min(ans, 4) = 4.

Then the shrink: subtract the left value, move left

To make the window shorter we take out the left element: total -= nums[left], then left += 1. Removing 2: sum 8 → 6. Now 6 < 7, the window [3, 1, 2] is no longer valid, so we stop shrinking and go back to expanding.

Why while, not if: her [1, 1, 1, 5] example

The teacher asks: should the shrink happen once (if) or repeatedly (while)? Take nums = [1, 1, 1, 5], target = 6.

grow1115sum 8 ≥ 6 → length 4 is valid
shrink 11115sum 7 ≥ 6 → still valid, length 3 is better
shrink 21115sum 6 ≥ 6 (equal counts) → length 2 is better still
shrink 31115sum 5 < 6 → invalid → stop shrinking

With an if, we'd shrink once and report 3. The correct answer is 2. So we keep shrinking until the condition becomes false. The last length recorded before it broke is the shortest valid window for this right end.

The rule in one sentenceExpand while the sum is too small. As soon as it's big enough, shrink while it's still big enough, recording the length each time.

Where exactly to record the answer

Inside the while, we record the length before removing the left element. At that moment the window is guaranteed valid (that's what the while condition just checked). After the loop ends, the window is invalid, so recording there would be wrong. This is the opposite of "longest window" problems, where you record after shrinking.

Doubt 1: she sometimes says "while sum is greater than target". Is it > or >=?
→ >=. The question says "greater than or equal to", and her own examples rely on it ([1, 2, 4] with sum exactly 7, and [1, 5] with sum exactly 6, are valid). With > you'd miss those.
Doubt 2: when left moves past an index, could the best answer still start at that index (with a later right)?
→ No. We only move left past index l when the window [l..right] was valid, and we recorded its length then. Any window [l..later right] is longer than that, so it can never be shorter than what we already recorded. That's why left never needs to go back, and the brute force's restarts were wasted work.
Doubt 3: can left run past right?
→ No. If the window became empty, its sum would be 0, and 0 ≥ target is impossible because target ≥ 1. So the while loop always stops while at least one element is still inside.

Continuing her dry run

5Approach steps

  1. left = 0, total = 0, ans = infinity.
  2. For each right: total += nums[right] (expand).
  3. While total ≥ target: record ans = min(ans, right − left + 1), then total -= nums[left] and left += 1 (shrink).
  4. After the loop: return 0 if ans is still infinity, else ans.

6Code (Python)

Optimal: sliding window, O(n)
class Solution:
    def minSubArrayLen(self, target, nums):
        total = 0                            # sum of the current window
        left = 0
        min_len = float('inf')               # "nothing found yet"
        for right in range(len(nums)):
            total += nums[right]             # expand: stretch the front
            while total >= target:           # valid: try to make it shorter
                min_len = min(min_len, right - left + 1)   # record first
                total -= nums[left]          # then pull the back in
                left += 1
        return 0 if min_len == float('inf') else min_len

7Code line by line

linewhat it means
total = 0 left = 0 min_len = float('inf')Empty window starting at index 0. min_len starts at infinity for the same reason as in Part A.
for right in range(len(nums)):The front of the leech: visits every index once. Moving to the next index is the "expand" step.
total += nums[right]Add the new element. total = sum(nums[left..right]).
while total >= target:The window is valid. Keep trying to shorten it, as many times as it stays valid.
min_len = min(min_len, right - left + 1)Record this valid window's length before shrinking (after shrinking it may be invalid).
total -= nums[left] left += 1Remove the leftmost element from the sum, then drop it from the window.
return 0 if min_len == float('inf') else min_lenThe teacher's ternary: if nothing valid was found, 0, otherwise the minimum length.

8Dry run

nums = [2, 3, 1, 2, 4, 3], target = 7. In the shrink column, each line is one pass of the while loop.

stepright (value added)window [left..right]sum after addingshrink? (what leaves, why)window after shrinkingmin_len so far
10 (2)[2] (0..0)2no, 2 < 7[2] (0..0)∞
21 (3)[2,3] (0..1)5no, 5 < 7[2,3] (0..1)∞
32 (1)[2,3,1] (0..2)6no, 6 < 7[2,3,1] (0..2)∞
43 (2)[2,3,1,2] (0..3)88 ≥ 7: record 4, 2 leaves → 6 < 7 stop[3,1,2] (1..3)4
54 (4)[3,1,2,4] (1..4)1010 ≥ 7: record 4, 3 leaves → 7
7 ≥ 7: record 3, 1 leaves → 6 < 7 stop
[2,4] (3..4)3
65 (3)[2,4,3] (3..5)99 ≥ 7: record 3, 2 leaves → 7
7 ≥ 7: record 2, 4 leaves → 3 < 7 stop
[3] (5..5)2

The array at the key moments (yellow = window, grey = left behind):

step 4231243sum 8, first valid window, length 4
L  R  
step 5231243after removing 3: sum 7, length 3 recorded
  L R 
step 6231243after removing 2: sum 7, length 2 recorded
    LR

Final answer: 2 ✓, the same as the brute force.

9Complexity & remember

She submitted it and it beat about 99.7%, as expected for a linear solution.

Remember the optimal for each right: total += x → while total ≥ target: record right − left + 1, total -= nums[left], left += 1.
Shortest-window problems record inside the while, before shrinking. Return 0 if nothing was recorded.

Part C · Revision page

Brute forceSliding window
ideafor each start, extend until sum ≥ target, record, breakexpand until valid, then shrink while valid, recording each length
loopstwo nested (j restarts for every i)one for + a while that never restarts
answer starts atinfinity (float('inf')), and becomes 0 at the end if never updated
time / spaceO(n²) / O(1), TLE for n = 10⁵O(n) (≈2n moves) / O(1)
Longest valid windowShortest valid window (this one)
shrink while…the window is invalidthe window is valid
record…after the while: maxinside the while, before removing: min
answer starts at0infinity
If you remember only 5 lines 1. Positive numbers → sum grows when you expand and drops when you shrink.
2. Expand right until the sum is ≥ target.
3. Then while it's still ≥ target: record the length, remove nums[left], move left.
4. Start the answer at infinity, not 0.
5. If it's still infinity at the end, return 0.
Mistakes to avoid ✗ starting min_len at 0
✗ forgetting to return 0 when no window works
✗ if instead of while for shrinking (misses [1, 5] in [1, 1, 1, 5])
✗ total > target instead of >=
✗ recording the length after the while loop (the window is invalid there)
✗ using this on arrays with negative numbers
test it yourself (paste under either Solution above)
s = Solution()
print(s.minSubArrayLen(7, [2, 3, 1, 2, 4, 3]))     # 2
print(s.minSubArrayLen(6, [1, 1, 1, 5]))           # 2  (needs while, not if)
print(s.minSubArrayLen(4, [1, 4, 4]))              # 1
print(s.minSubArrayLen(11, [1, 1, 1, 1, 1, 1]))    # 0  (no valid window)
print(s.minSubArrayLen(20, [2, 3, 1, 2, 4, 3]))    # 0  (total is only 15)
print(s.minSubArrayLen(15, [2, 3, 1, 2, 4, 3]))    # 6  (the whole array)

Based on this video: Minimum Size Subarray Sum | Sliding Window