AlgoMaster Logo

Maximum Subarray

mediumFrequency7 min readUpdated June 23, 2026

Understanding the Problem

We need to find a contiguous portion of the array whose elements add up to the largest possible sum. The subarray must contain at least one element, so we can't return 0 for an array of all negatives.

The complication is that negative numbers can appear anywhere. A subarray like [4, -1, 2, 1] has a sum of 6, which beats [4] alone, even though there's a -1 in the middle. So we cannot skip all negatives. The question is when it pays to absorb a negative number to reach larger positives later, and when to abandon the current subarray and start a new one. Each approach below resolves that question differently.

Key Constraints:

  • nums.length up to 10^5 means an O(n^2) scan does up to 10^10 operations and times out. We need O(n log n) or better.
  • Elements can be negative (-10^4 <= nums[i] <= 10^4), so we cannot skip negatives or use a sliding window that assumes the sum only grows as the window widens.
  • The array is non-empty (length >= 1), so there is always at least one valid subarray, and the answer for an all-negative array is the largest single element rather than 0.

Approach 1: Brute Force

Intuition

Check every possible subarray and keep the largest sum. A subarray is defined by its start and end index, so we try every valid pair.

For each starting index i, we extend the subarray one element at a time, adding each new element to a running sum. Reusing this running sum avoids recomputing each subarray's total from scratch, which saves a loop compared to the O(n^3) version that re-sums every subarray.

Algorithm

  1. Initialize maxSum to the first element (since the subarray must contain at least one element)
  2. For each starting index i from 0 to n-1:
    • Initialize currentSum to 0
    • For each ending index j from i to n-1:
      • Add nums[j] to currentSum
      • Update maxSum if currentSum is larger
  3. Return maxSum

Example Walkthrough

1i=0, j=0: sum=-2, maxSum=-2
0
i
-2
j
1
1
2
-3
3
4
4
-1
5
2
6
1
7
-5
8
4
1/12

Code

The brute force repeats work: it recomputes overlapping subarray sums again and again. The next approach processes each element once, deciding at every position whether to extend the current subarray or begin a new one.

Approach 2: Kadane's Algorithm

Intuition

At each position in the array, the maximum subarray ending at that position is either the element itself, or the element plus the maximum subarray ending at the previous position. That single observation removes the need to consider every start index separately.

At index i, with the best subarray sum ending at index i-1 known, there are two choices:

  • Extend: Add nums[i] to the previous subarray, giving previousBestSum + nums[i].
  • Start a new subarray: Begin again at nums[i], giving nums[i] alone.

Starting a new subarray wins exactly when previousBestSum is negative, since a negative running sum can only reduce whatever follows. The decision rule is currentSum = max(nums[i], currentSum + nums[i]).

While making this local decision at every index, we track the largest currentSum seen across all positions. That global maximum is the answer.

Algorithm

  1. Initialize currentSum and maxSum both to nums[0]
  2. For each element from index 1 to n-1:
    • Set currentSum to the larger of nums[i] and currentSum + nums[i]
    • Update maxSum if currentSum is larger
  3. Return maxSum

Example Walkthrough

1Init: currentSum=-2, maxSum=-2
0
-2
1
1
2
-3
3
4
4
-1
5
2
6
1
7
-5
8
4
1/10

Code

Kadane's is O(n), which is optimal here since the answer can depend on every element. The problem also lists a divide and conquer follow-up. It runs in O(n log n), slower than Kadane's, but it applies a different paradigm and is the standard divide and conquer treatment of this problem.

Approach 3: Divide and Conquer

Intuition

Split the array at the midpoint. The maximum subarray then falls into exactly one of three cases:

  1. Entirely in the left half
  2. Entirely in the right half
  3. Crossing the midpoint (starts in the left half, ends in the right half)

These three cases cover every possibility, because a subarray either stays on one side of the boundary between mid and mid+1 or straddles it. The left and right cases are solved by recursion. For the crossing case, the subarray must contain both nums[mid] and nums[mid+1], so its best value is the best suffix of the left half ending at mid plus the best prefix of the right half starting at mid+1. We find each by extending outward from the boundary one element at a time. The answer is the largest of the three.

Algorithm

  1. Base case: If the subarray has one element, return that element
  2. Find the midpoint mid
  3. Recursively find the maximum subarray sum in the left half: leftMax
  4. Recursively find the maximum subarray sum in the right half: rightMax
  5. Find the maximum crossing subarray sum:
    • Starting from mid, extend left, tracking the best sum: leftCrossMax
    • Starting from mid + 1, extend right, tracking the best sum: rightCrossMax
    • Crossing sum = leftCrossMax + rightCrossMax
  6. Return the maximum of leftMax, rightMax, and the crossing sum

Example Walkthrough

1Top call: left=0, right=8, mid=4. Left half=indices 0-4, Right half=indices 5-8
0
-2
1
1
2
-3
3
4
4
-1
mid
5
2
6
1
7
-5
8
4
1/7

Code