The Quest Begins (The “Why”)
I still remember the first time I faced a coding interview that asked for the maximum sum subarray. I stared at the prompt, scribbled a double‑loop, and watched my solution crawl to O(n²) like a tired hobbit trudging through Mordor. The interviewer’s polite nod felt more like a pity‑clap than a win. I walked away thinking, “There’s got to be a smarter way.”
That moment lit a fire under me. I dug into dynamic programming not because I wanted to memorize a template, but because I wanted to understand why a few extra variables could turn a quadratic nightmare into a linear sprint. If you’ve ever felt stuck rewriting the same loops over and over, you know the frustration. Let’s turn that frustration into power.
The Revelation (The Insight)
The secret sauce behind Kadane’s algorithm (the O(n) solution for maximum subarray sum) is optimal substructure combined with a tiny bit of state‑carrying.
Think of the array as a path. At each position i you have two choices:
- Start a new subarray at i (if everything before i is dragging you down).
- Extend the previous subarray by adding a[i] to it.
If we know the best sum that ends at position i‑1, we can decide in O(1) time whether to keep that streak or break it. That’s the overlapping subproblem: the answer for i depends only on the answer for i‑1, not on the whole history.
So we keep just one variable, current, that stores the maximum sum of a subarray that must end at the current index. Another variable, best, records the highest current we’ve seen so far.
Why does this work? Because any optimal subarray either ends at the current index (captured by current) or it ended earlier (captured by best). By scanning left‑to‑right we never miss a candidate, and we never recompute anything. It’s like having a magic compass that always points to the best treasure you’ve seen so far while you walk the path.
Wielding the Power (Code & Examples)
The Struggle – Brute Force
function maxSubarrayBrute(arr) {
let best = -Infinity;
for (let i = 0; i < arr.length; i++) {
let sum = 0;
for (let j = i; j < arr.length; j++) {
sum += arr[j];
if (sum > best) best = sum;
}
}
return best;
}
Two nested loops → O(n²). For an array of 10⁵ elements this is a non‑starter.
The Victory – Kadane’s Algorithm
function maxSubarrayKadane(arr) {
let current = arr[0]; // best sum ending here
let best = arr[0]; // best sum anywhere so far
for (let i = 1; i < arr.length; i++) {
// Either extend the previous subarray or start fresh at i
current = Math.max(arr[i], current + arr[i]);
best = Math.max(best, current);
}
return best;
}
Why it’s O(n): The loop touches each element once, doing only constant‑time work inside. No recursion, no extra data structures—just two integers that get updated.
Common Traps
| Trap | What happens | How to avoid |
|---|---|---|
Resetting current to 0 when all numbers are negative |
Returns 0 (empty subarray) which is often not allowed | Initialize with the first element and use Math.max(arr[i], current + arr[i])
|
Forgetting to update best after computing current
|
You might miss the optimal subarray that ends at the last index | Update best every iteration, as shown above |
Real‑World Interview Flavors
Maximum Subarray Sum (the classic).
Input:[-2,1,-3,4,-1,2,1,-5,4]→ Output:6(subarray[4,-1,2,1]).Best Time to Buy and Sell Stock I (LeetCode 121).
Treat each day's price asp[i]. The profit if you sell on day i after buying on the cheapest day before it isp[i] - minPriceSoFar. This is exactly Kadane’s formulation on the array of daily differencesdiff[i] = p[i] - p[i‑1].
function maxProfit(prices) {
let minPrice = prices[0];
let maxProfit = 0;
for (let i = 1; i < prices.length; i++) {
minPrice = Math.min(minPrice, prices[i]);
maxProfit = Math.max(maxProfit, prices[i] - minPrice);
}
return maxProfit;
}
Same O(n) heartbeat, same idea: keep the best “state” so far and update it in constant time.
Why This New Power Matters
Now you can slay any problem that reduces to “pick a contiguous segment that maximizes/minimizes something” in linear time. Think of budgeting, signal processing, or even DNA sequence alignment where you need the best local match. The pattern—maintain the optimal answer that ends at the current position—is a reusable spell. Once you internalize it, you’ll start spotting DP opportunities where you once saw only nested loops.
I still get a grin when I see a candidate whip out Kadane’s in under five minutes; it’s like watching a knight draw a sword and instantly cleave the dragon.
Your Turn
Grab an array of integers (maybe your daily step counts) and compute the longest period where the cumulative sum stays above zero. Or tweak Kadane to track the indices of the best subarray. Share your solution in the comments—let’s see who can craft the most creative twist!
Happy coding, and may your algorithms always be O(n) and your bugs be O(0). 🚀
Top comments (0)