Consider two problems on the array [2, 3, 1, 2, 4, 3] with target 7:
Problem A: Find the shortest subarray with sum >= 7.
Problem B: Find the longest subarray with sum <= 7.
Both use expand/shrink. Both have a left pointer and a right pointer. The variable-size template looks identical.
But one needs while to shrink. The other needs if. Use the wrong one and your answer is silently wrong --- no crash, no error, just a bad result that passes most test cases.
Here is what makes this so treacherous. Both versions compile. Both run without exceptions. Both even produce reasonable-looking numbers. The bug only reveals itself on specific inputs where the difference between “shrink once” and “shrink until invalid” actually matters. In a contest, you might not catch it until you have already submitted.
Toggle between the two strategies and watch how far the left pointer travels:
while-shrink found the tightest window (length 3)
Before moving on: which problem needs while, and why?
This is the kind of bug that costs people interviews. Not because it is hard to fix --- the fix is changing one keyword --- but because the broken version looks almost right. It compiles. It runs. It even passes most test cases. The failure only surfaces on specific inputs where “shrink once” and “shrink until invalid” produce different left-pointer positions.
You are about to run both versions side by side on the array [2, 3, 1, 2, 4, 3] with target 7. Same array, same target, same expand logic. The only difference: one version shrinks with if, the other with while.
On the previous screen you toggled between the two strategies and saw the left pointer behave differently. Now you will trace both executions step by step. The question is: at which exact step do the two strategies diverge, and what is the consequence for the answer? If if only trims once per expansion, the left pointer falls behind --- which means the window stays wider than necessary. Wider means longer. And if you are looking for the shortest valid window, a lazy left pointer reports the wrong answer.
Watch both executions. Spot the exact step where the lagging pointer produces a window length that the while version already trimmed past.
Find the SHORTEST subarray of 231243 with sum ≥ 7.
We will use a variable-size sliding window. After expanding to find a valid window, we need to shrink from the left. But HOW MUCH should we shrink?
When you find a valid window, should you shrink ONCE (if) or KEEP shrinking (while)?
You just saw the bug in action. Before the rule is stated --- commit to your answer:
For a 'minimum valid window' problem (e.g. shortest subarray with sum >= target), do you shrink with if or while?
Here is the rule, stated plainly:
while-shrink: Use when you want the shortest valid window. After the window becomes valid, keep shrinking to find the minimum. Every valid window encountered during shrinking is a candidate for the answer.
// LC 76: Minimum Window Substringwhile (windowIsValid()) { answer = Math.min(answer, right - left + 1); removeFromWindow(s[left]); left++;}if-shrink: Use when you want the longest valid window. Shrink only enough to restore validity, then record the answer. Over-shrinking would skip valid windows that might be the longest.
// LC 904: Fruit Into Baskets (max length, at most 2 types)if (map.size > 2) { removeFromWindow(fruits[left]); left++;}answer = Math.max(answer, right - left + 1);The mental model: while compresses, if trims. while squeezes the window down as far as it can go --- finding the tightest valid fit. if only removes one element to get back to valid, preserving maximum length.
Here is a quick-reference table for interview use:
| You want... | Shrink with | Record answer | Classic problem |
|---|---|---|---|
| Shortest valid window | while | Inside the loop | LC 76: Min Window Substring |
| Longest valid window | if | After the check | LC 904: Fruit Into Baskets |
| Count of valid windows | while | count += right - left + 1 | LC 992: Subarrays with K Different Integers |
| First valid window | while + break | Inside the loop, then return | LC 567: Permutation in String |
The “count” row might surprise you. Counting valid subarrays uses while-shrink because you need to find the tightest left boundary for each right position --- every subarray between left and right is valid, so the count at each step is right - left + 1.
One last gotcha: the if-shrink pattern sometimes appears as while with an early break, especially when the validity condition is complex. The key question is always the same: are you seeking the minimum or the maximum? Minimum means compress with while. Maximum means trim with if.