Permit Streaks: counting the ranges that sum to target
A daily feed of building-permit counts — zeros allowed, corrections can go negative. The ask: how many contiguous date ranges sum to exactly target? This is a guided walk-through — press Play on each figure, and leave able to explain the O(n) trick, not just type it.
Turn it into a prefix-sum lookup
The one sentence to keep in your pocket — say it cleanly and stop:
map[sum − target]. One pass — O(n) time, O(n) space."That's the whole solution. The rest of this page is why it works and how to defend it under pressure — including the question that separates a junior answer from a senior one: why not just slide a window?
Brute force: every range
Start simple. There are about n²/2 contiguous ranges; score each one against target. Correct, easy to write — and quadratic.
Two nested loops = O(n²). The fix isn't a cleverer loop — it's reframing the question so each day's answer is a single lookup.
A range is one subtraction
The whole trick rests on one identity. Precompute running totals, and the sum of any range becomes the difference of two of them — no re-adding.
One pass with a hash map
Sweep left to right. Carry the running prefix sum and a map of how many times each prefix value has occurred. At each day, the ranges ending there are already counted in the map.
{0: 1} — the empty prefix, seen once. (That seed is what lets a range starting on day 0 get counted.) sum = 0, answer = 0.Each day is O(1): one add, one lookup, one insert. n days ⟶ O(n) time, O(n) space. That's the answer the interviewer is fishing for.
Why not a sliding window?
The instinct for "contiguous range summing to target" is two pointers. Here it's a trap — and naming why earns the most points in the whole problem. Flip the toggle and watch the prefix sum.
The edge cases that break naive code
Four traps an interviewer will probe — each one is handled for free once the prefix-sum map is set up correctly.
The interview cheat-sheet
map[sum − target] to the answer, then bump map[sum]. O(n) time, O(n) space.sum − target.{0: 1}, store counts (not seen/unseen), and look up before inserting. target = 0 works with no special case.map[sum − target] — one pass, O(n). A sliding window won't work because the feed allows zeros and corrections, so the sum isn't monotonic."