150NeetCode 150

122.Maximum Subarray

MediumBlind 75Greedy Ā· 1/8

Problem

Given an integer array nums, find the contiguous subarray (containing at least one element) with the largest sum, and return that sum.

Examples

Input:  nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: The subarray [4,-1,2,1] has sum 6.
Input:  nums = [1]
Output: 1
Input:  nums = [5,4,-1,7,8]
Output: 23
Explanation: The whole array is the best subarray.
Input:  nums = [-3,-1,-2]
Output: -1
Explanation: All values are negative, so the best is the single largest element.

Constraints

  • 1 <= nums.length <= 10^5
  • -10^4 <= nums[i] <= 10^4

šŸ’” Key Insight

Let cur be the best sum of a subarray that ends at index i. Either we extend the previous best (cur + nums[i]) or start fresh at nums[i] — and we should start fresh exactly when the running sum has become negative, because a negative prefix can only drag down anything after it. This is Kadane's algorithm: one pass, two variables.

Brute Force

TimeO(n²)SpaceO(1).

Intuition

Try every starting index i, extend the subarray one element at a time, and track the running sum. The best running sum seen anywhere is the answer.

Algorithm

  1. best = nums[0].
  2. For each i: sum = 0; for each j >= i: sum += nums[j], best = max(best, sum).
  3. Return best.

Visualization

nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]

i=3: sums 4, 3, 5, 6, 1, 5   -> best becomes 6 at j=6 ([4,-1,2,1])

Code

java
class Solution {
    public int maxSubArray(int[] nums) {
        int best = nums[0];
        for (int i = 0; i < nums.length; i++) {
            int sum = 0;
            for (int j = i; j < nums.length; j++) {
                sum += nums[j]; // sum of nums[i..j]
                best = Math.max(best, sum);
            }
        }
        return best;
    }
}

Complexity

  • Time: O(n²) — every pair (i, j); too slow for n = 10^5.
  • Space: O(1).

Complexity Comparison

Approach Time Space
Brute Force O(n²) O(1)
Divide and Conquer O(n log n) O(log n)
Kadane's Algorithm O(n) O(1)

Common Pitfalls

  • Initialising best = 0 — returns 0 for an all-negative array instead of the largest element.
  • Resetting cur to 0 before adding the current element and then comparing, which can also report 0 incorrectly for all-negative input.
  • Confusing subarray (contiguous) with subsequence — you cannot skip negative elements in the middle.
  • In divide and conquer, forgetting that the crossing sum must include both nums[mid] and nums[mid + 1].