Two Problems, Same Code, Different Bugs

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:

2
0
3
1
L
1
2
2
3
R
4
4
3
5
window length = 3sum = 7

while-shrink found the tightest window (length 3)

Before moving on: which problem needs while, and why?

Feel the Bug

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.

Phase 1: The First Attempt

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)?

The Rule

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.

1
// LC 76: Minimum Window Substring
2
while (windowIsValid()) {
3
  answer = Math.min(answer, right - left + 1);
4
  removeFromWindow(s[left]);
5
  left++;
6
}

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.

1
// LC 904: Fruit Into Baskets (max length, at most 2 types)
2
if (map.size > 2) {
3
  removeFromWindow(fruits[left]);
4
  left++;
5
}
6
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 withRecord answerClassic problem
Shortest valid windowwhileInside the loopLC 76: Min Window Substring
Longest valid windowifAfter the checkLC 904: Fruit Into Baskets
Count of valid windowswhilecount += right - left + 1LC 992: Subarrays with K Different Integers
First valid windowwhile + breakInside the loop, then returnLC 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.