DSA sheet / Sorting and searching

Maximum Subarray Sum

medium about 20 min kadanedynamic-programming
Open on CSES

Do these first: Repetitions

The problem in brief

Given n integers (n up to 200 000, each between -10^9 and 10^9, possibly negative), print the maximum sum of any non-empty consecutive block of them.

Try it

Tab indents; press Esc, then Tab, to leave the box. Ctrl+Enter runs.

Hints

Stuck? Reveal one hint at a time. Each nudges without giving away the next.

The walkthrough

Spoilers ahead: open a section only after you have given the hints a fair try.

How to think

This is the canonical “subproblem per end position” idea. Define f(i) = the best sum of a block ending exactly at i. Any such block either is just a[i] or is a block ending at i - 1 extended by a[i], so f(i) = a[i] + max(0, f(i - 1)). That recurrence needs only the previous value, so you keep one running number. The answer is the maximum f(i) seen. This is Kadane’s algorithm, and the reasoning that discards negative prefixes is the whole trick.

There is a second view that connects to prefix sums: a block sum equals P[j] - P[i - 1], so the best block ending at j uses the smallest earlier prefix. Both give O(n).

Common trap: initialising the best answer to 0 is wrong when all numbers are negative, because the block must be non-empty. Start from the first element. The habit: define the state as “best answer that ends here”, write the recurrence, and check the degenerate inputs.

Intuition

Walk along keeping a running total. If the running total ever drops below zero, it is dead weight: you are better off forgetting it and starting from the next element. Keep track of the highest total you ever held.

Approach
  1. Set cur = a[0] and best = a[0].
  2. For each next element x: cur = max(x, cur + x); best = max(best, cur).
  3. Print best.

Pitfalls: sums can reach 2 * 10^5 * 10^9 = 2 * 10^14, so use 64-bit; initialise from the first element so all-negative inputs work; a single element is a valid answer.

Complexity

O(n) time, O(1) memory beyond the input.

Solutions

Written from scratch and checked by compiling and running each one against a brute force on random inputs. Fast input/output, the way you would submit it.

Show solutions (C++17, Python 3, Java 17, Node.js)
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    long long cur = 0, best = 0;
    for (int i = 0; i < n; i++) {
        long long x;
        cin >> x;
        cur = (i == 0) ? x : max(x, cur + x);
        best = (i == 0) ? x : max(best, cur);
    }
    cout << best << "\n";
    return 0;
}

Problem: CSES Problem Set (Antti Laaksonen, University of Helsinki), CC BY-NC-SA 4.0. The explanations and code above are original (© Anupam Kumar).

Related problems

Back to the sheet