0
Find the contiguous subarray with the largest sum using Kadane's algorithm — at each index, decide in one comparison whether to extend the running window or cut the dead weight and restart fresh.
Given an integer array, return the sum of the contiguous subarray with the largest sum. For nums = [-2,1,-3,4,-1,2,1,-5,4], the answer is 6 — the subarray [4,-1,2,1] at indices 3–6. The array may contain negative numbers; the answer is always at least one element (the problem guarantees a non-empty input).
i, the best subarray ending at i is either just nums[i] alone, or curSum + nums[i] (the best ending at i-1, extended). Choose the larger: curSum = max(nums[i], curSum + nums[i]). If curSum was negative, extending with it only hurts — throw it away and start fresh. Track the global maximum as you go.curSum = best = nums[0]. This handles the single-element edge case and means we never touch -Infinity.nums[i]:curSum = max(nums[i], curSum + nums[i])best = max(best, curSum) — save the largest running sum seen so far.best. One pass, O(n) time, O(1) space.curSum = 0 and then wonder why an all-negative array returns 0 instead of the least-negative element. The fix: seed with nums[0] and start the loop at index 1. Alternatively, the max(nums[i], curSum + nums[i]) form is self-correcting — when curSum < 0 the first branch wins automatically.To reconstruct the indices, track a windowStart pointer that resets whenever you restart, and save bestStart / bestEnd whenever you update best. No extra space asymptotically.
function maxSubArray(nums: number[]): number {
let curSum = nums[0];
let best = nums[0];
for (let i = 1; i < nums.length; i++) {
// Drop the prefix the moment it hurts: if curSum < 0, extending with it
// only makes the new subarray smaller than starting fresh at nums[i].
curSum = Math.max(nums[i], curSum + nums[i]);
best = Math.max(best, curSum);
}
return best;
}curSum and best at nums[0] correctly handles an all-negative array (the answer is the largest single element, never a fabricated 0).curSum = max(nums[i], curSum + nums[i]) is the whole algorithm. When curSum is negative, extending it would shrink the total, so the first branch wins and we restart the window at i. When curSum ≥ 0, extending is always at least as good as starting fresh, so the second branch wins.best only ever grows.[-2,1,-3,4,-1,2,1,-5,4] this returns 6.curSum, best) beyond the input.windowStart that resets to i on restart, and save bestStart / bestEnd whenever best updates.total - minSubarraySum. Take the max of both cases; watch the all-negative edge case.maxSoFar and minSoFar because a negative times a negative can become the new max.(start, end) pair. Kadane exploits the fact that a subarray with a negative prefix can always be improved by dropping that prefix.nums[0] handles this; a curSum = 0 seed would silently return 0, which is wrong.| "maximum / minimum contiguous subarray" | Kadane's (extend or restart) |
| running sum turns negative → should we keep it? | restart window at cur index |
| track prefix decision at every step | max(nums[i], curSum + nums[i]) |
| "best time to buy/sell stock" (daily diffs) | Kadane's on profit array |
function maxSubArray(nums: number[]): number {
let curSum = nums[0];
let best = nums[0];
for (let i = 1; i < nums.length; i++) {
curSum = Math.max(nums[i], curSum + nums[i]);
best = Math.max(best, curSum);
}
return best;
}nums = [-2,1,-3,4,-1,2,1,-5,4], what is the maximum subarray sum?curSum = Math.max(nums[i], curSum + nums[i]) restart the window when the running sum is negative?curSum = 0 (instead of nums[0]) for the input [-3,-1,-2]?nums = [1] (single element), what does the algorithm return?