recur
BlogDP · 1D

Kadane's, derived from scratch in four lines

RC
Recur TeamJun 20, 2026 · 2 min read

Maximum Subarray is the canonical “I memorized it, then blanked on it” problem. The fix isn’t better memorization — it’s deriving the recurrence from a framing so natural you can rebuild it cold.

The framing that does all the work

Ask one question: what’s the best subarray that ends exactly at index i?

Call it end_here[i]. Every subarray ends somewhere, so the global answer is just the best of these: max(end_here). That’s the whole decomposition — no clever insight required yet.

Now the recurrence writes itself. A subarray ending at i either extends the best subarray ending at i-1, or it starts fresh at i. There is no third option — that’s what “contiguous” means:

end_here[i] = max(end_here[i - 1] + nums[i], nums[i])

When does starting fresh win? Exactly when end_here[i-1] is negative — a negative prefix can only drag you down, so you drop it. People memorize “reset when the running sum goes negative” as a trick; it’s not a trick, it’s the max doing its job.

Collapsing to four lines

end_here[i] only ever looks at end_here[i-1], so the array collapses to a single variable:

def max_subarray(nums):
    cur = best = nums[0]
    for n in nums[1:]:
        cur = max(cur + n, n)
        best = max(best, cur)
    return best

O(n) time, O(1) space, and every line traces back to a sentence you can say out loud: cur is the best subarray ending here; best is the best seen anywhere; extend or restart, whichever is larger.

Why this survives the follow-ups

Because the derivation generalizes and the memorized line doesn’t:

Coach’s note · On your next review, don’t start with the code. Start by defining end_here[i] in one sentence. If the sentence is right, the four lines are inevitable.

All posts