Skip to main content

Maximum Subarray

How to notice that the real question is whether the previous sum still helps or whether it is now hurting.

Given an integer array nums, find the contiguous subarray with the largest sum and return that sum.

Example:

Input:  nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
Output: 6

The subarray [4, -1, 2, 1] has sum 6.

What to notice before coding

Common mistakes

Step 1 — Understand the one word that changes everything

The prompt says contiguous subarray.

That kills a common bad reading: picking scattered numbers that look good and adding them together.

You cannot skip.

The answer has to be one continuous block.

Step 2 — Write the correct baseline

A good baseline is to test every possible subarray, while summing incrementally:

export function maxSubArray(nums: number[]): number {
  let best = -Infinity

  for (let start = 0; start < nums.length; start += 1) {
    let sum = 0

    for (let end = start; end < nums.length; end += 1) {
      sum += nums[end]
      best = Math.max(best, sum)
    }
  }

  return best
}

It works. But it still tests every start against every end.

Step 3 — Ask what matters at the current position

When you reach nums[i], what do you want to know?

You do not need the best sum of the whole array yet.

The local question is:

what is the best subarray sum that ends exactly here?

That leads to the key idea:

  • if the previous sum helps, keep it
  • if the previous sum hurts, restart at the current value

Step 4 — Store the best sum ending here

That becomes a very simple recurrence:

bestEndingHere = max(value, bestEndingHere + value)

Then compare that with the best global answer.

That is the whole idea behind Kadane.

The interactive editor needs JavaScript. You can still read the prompt and copy the starter code below.

Starter code

export function maxSubArray(nums: number[]): number {
  // your solution here
  return 0
}
solution.ts
Stuck? Hints available.

Haven't solved it yet?

Viewing the solution now may reduce learning. It's worth trying a bit more.

Open the reference solution

Without JavaScript, the reference solution is shown inline instead of in a dialog.

Solution

Final complexity

Time: O(n)

Space: O(1)

Solution 1 — Test all subarrays O(n²)

A decent baseline is to fix the start and keep extending the end.

export function maxSubArray(nums: number[]): number {
  let best = -Infinity

  for (let start = 0; start < nums.length; start += 1) {
    let sum = 0

    for (let end = start; end < nums.length; end += 1) {
      sum += nums[end]
      best = Math.max(best, sum)
    }
  }

  return best
}

Correct, but still quadratic.

Solution 2 — Kadane O(n)

If the local question is “what is the best sum ending here?”, one pass is enough.

export function maxSubArray(nums: number[]): number {
  let bestEndingHere = nums[0]
  let bestOverall = nums[0]

  for (let index = 1; index < nums.length; index += 1) {
    const value = nums[index]

    bestEndingHere = Math.max(value, bestEndingHere + value)
    bestOverall = Math.max(bestOverall, bestEndingHere)
  }

  return bestOverall
}

The algorithm looks short because the question was reduced to the right state.

What to say in the interview

A strong short explanation would be:

The baseline tests all subarrays and costs O(n²). The optimized version stores the best subarray sum ending at the current index. If the previous sum helps, I keep it. If it hurts, I restart at the current value. That reduces the problem to O(n).

That shows that you:

  • respected the contiguity constraint
  • turned a global problem into a local one
  • explained Kadane as reasoning, not a memorized name

When this pattern shows up again

Many people describe Kadane as a form of dynamic programming with tiny state.

In some explanations, it also feels greedy, because the local choice to continue or restart is exactly what keeps the best running segment alive.

The same pattern comes back when you need to:

  • decide whether to continue or restart
  • keep a best local answer while scanning
  • compress dynamic programming into tiny state
  • explain why a local decision works

The point is not memorizing “Kadane.”

The point is noticing when the right state is “best answer ending here.”

Next challenge Binary Search Previous challenge Best Time to Buy and Sell Stock

Related challenges

Related articles