Home › Blog › Kadane's Algorithm

Kadane's Algorithm Explained: Template, Trace and Problems

The one-loop maximum subarray algorithm, why it is correct, and how to adapt it to products, circular arrays and stock prices, with Python we ran and tested.

Kadane's algorithm finds the largest sum of any contiguous subarray in one pass: at each element, either extend the current run or start a new run at that element, and keep the best total seen, which gives O(n) time and O(1) space. Use it when a problem asks for the maximum (or minimum) sum, product or score of a contiguous subarray and the values can be negative.

Below: the template, a step-by-step trace, why it is correct, three worked LeetCode problems (53, 152 and 918), the bugs interviewers watch for and a practice list. Every code block on this page was run in Python with asserts against a brute-force check of all subarrays before we published it.

When to use Kadane's algorithm

How Kadane's algorithm works

Keep two numbers while you scan left to right:

For each new value x, the best subarray ending here either continues the previous run (curr + x) or starts fresh (x). Take whichever is larger. If curr was negative, carrying it forward can only hurt, so the algorithm restarts.

Step-by-step trace

Input: [-2, 1, -3, 4, -1, 2, 1, -5, 4] (the example from LeetCode 53).

xcurr + xNew curr = max(x, curr + x)bestDecision
-2start-2-2First element
1-111Restart at 1
-3-2-21Extend
4244Restart at 4
-1334Extend
2555Extend
1666Extend
-5116Extend
4556Extend

The answer is 6, from the subarray [4, -1, 2, 1].

Why it is correct

Kadane's algorithm is a one-dimensional dynamic program with the state compressed to a single variable. Let dp[i] be the best sum of a subarray ending at index i. Any such subarray is either nums[i] alone or a subarray ending at i - 1 plus nums[i], so dp[i] = max(nums[i], dp[i - 1] + nums[i]). The answer is the maximum of all dp[i]. Because each dp[i] needs only dp[i - 1], one variable replaces the array. If you want the broader DP picture, see our dynamic programming patterns guide.

The Python template

This is the complete solution to Maximum Subarray (LeetCode 53).

def max_subarray(nums):
    best = curr = nums[0]
    for x in nums[1:]:
        curr = max(x, curr + x)   # extend the current run, or start a new one at x
        best = max(best, curr)    # remember the best run seen so far
    return best

Initialize both variables with nums[0], not 0. Starting at 0 silently returns 0 for an all-negative array such as [-3, -1, -2], where the correct answer is -1. (Some variants allow an empty subarray with sum 0; then starting at 0 is correct. Ask which one the interviewer means.)

Returning the subarray, not just the sum

A common follow-up: "Which subarray is it?" Track where the current run started and copy it when you find a new best.

def max_subarray_with_bounds(nums):
    best = curr = nums[0]
    start = best_l = best_r = 0
    for i in range(1, len(nums)):
        if curr < 0:               # a negative run only hurts: restart at i
            curr, start = nums[i], i
        else:
            curr += nums[i]
        if curr > best:
            best, best_l, best_r = curr, start, i
    return best, best_l, best_r    # sum, first index, last index (inclusive)

Worked problem 1: Maximum Product Subarray (LeetCode 152)

Maximum Product Subarray (LeetCode 152) looks like Kadane with * instead of +, but a negative number turns the smallest product into the largest. The idea: track both the largest (hi) and smallest (lo) product ending at the current index, and swap them when x is negative. A zero resets both, because max(x, hi * x) becomes 0 and the next element starts fresh.

def max_product(nums):
    best = hi = lo = nums[0]
    for x in nums[1:]:
        if x < 0:
            hi, lo = lo, hi        # a negative number flips the largest and smallest
        hi = max(x, hi * x)
        lo = min(x, lo * x)
        best = max(best, hi)
    return best

Complexity: O(n) time, O(1) space.

Worked problem 2: Maximum Sum Circular Subarray (LeetCode 918)

In Maximum Sum Circular Subarray (LeetCode 918), the subarray may wrap from the end of the array to the start. The idea: the best subarray either does not wrap (plain Kadane for the maximum) or wraps, in which case it is the whole array minus the minimum subarray in the middle. Run Kadane for the max and the min in the same loop and take max(best_max, total - best_min).

def max_subarray_sum_circular(nums):
    total = 0
    cur_max = cur_min = 0
    best_max = best_min = nums[0]
    for x in nums:
        cur_max = max(x, cur_max + x)
        best_max = max(best_max, cur_max)
        cur_min = min(x, cur_min + x)
        best_min = min(best_min, cur_min)
        total += x
    if best_max < 0:               # every number is negative: wrapping would mean an empty subarray
        return best_max
    return max(best_max, total - best_min)

Complexity: O(n) time, O(1) space. The edge case is the whole point: if every number is negative, total - best_min equals 0, which corresponds to an empty subarray and is not allowed, so return best_max.

Worked problem 3: Best Time to Buy and Sell Stock (LeetCode 121)

Buying on day i and selling on day j earns prices[j] - prices[i], which equals the sum of the daily changes between those days. So the best single trade is the maximum subarray of the daily price changes, with an empty subarray (no trade, profit 0) allowed. That is why curr and best start at 0 here.

def max_profit(prices):
    best = curr = 0
    for i in range(1, len(prices)):
        curr = max(0, curr + prices[i] - prices[i - 1])   # Kadane on daily price changes
        best = max(best, curr)
    return best

Complexity: O(n) time, O(1) space. The more common solution tracks the minimum price so far; both are correct, and showing you can see the Kadane version is a strong signal in an interview.

Kadane's algorithm complexity and alternatives

ApproachTimeExtra spaceWhen to mention it
Brute force over all subarrays (running sum)O(n²)O(1)As your starting point, then improve
Prefix sums: max of prefix[j] minus the smallest earlier prefixO(n)O(1) if done on the flyEquivalent; useful if you think in prefix sums
Divide and conquer (best left, best right, best crossing the middle)O(n log n)O(log n) recursionLeetCode 53's own follow-up asks for it
Kadane's algorithmO(n)O(1)The expected final answer

To feel the gap between O(n²) and O(n) on 100,000 elements (LeetCode 53's upper limit on array length), try the free Big-O complexity visualizer.

Common bugs and edge cases

Tip: State the invariant before coding: "curr is the best sum of a subarray ending at index i." Interviewers care more about that sentence than the four lines that follow it.

Practice list: 8 Kadane problems

#ProblemDifficultyTwist
53Maximum SubarrayMediumThe template
121Best Time to Buy and Sell StockEasyKadane on daily changes, empty allowed
152Maximum Product SubarrayMediumTrack max and min
918Maximum Sum Circular SubarrayMediumTotal minus minimum subarray
1749Maximum Absolute Sum of Any SubarrayMediummax(best max, -best min)
2606Find the Substring With Maximum CostMediumMap characters to values, then Kadane
1186Maximum Subarray Sum with One DeletionMediumTwo states: no deletion yet, one deletion used
1191K-Concatenation Maximum SumMediumKadane on two copies plus whole-array sums

Problem numbers and difficulty labels were checked on LeetCode as of October 2026. Several of these appear in the Blind 75 and the NeetCode 150.

How to practice explaining it

Kadane's algorithm is short enough that interviewers judge you on the explanation: the invariant, the all-negative case, and the follow-up variants. Practice saying it out loud. CoPilot Interview's Mock Interview can mix coding questions into a practice session; it reads each question aloud and scores your spoken answer out of 10 with what to fix and a model answer. For a quick session with nothing to install, the browser mock at /ai-mock-interview has 113 questions across 9 tracks, including coding. For a one-page refresher, keep the coding interview cheat sheet open.

Explain Kadane's algorithm like you would in the interview

Take a free AI mock interview in your browser, answer a coding question out loud, and see what to tighten.

Try a free AI mock interview

FAQ

What is Kadane's algorithm?

Kadane's algorithm finds the maximum sum of a contiguous subarray in one pass. For each element it decides whether to extend the current run or start a new one at that element, and it keeps the best sum seen. It runs in O(n) time and O(1) extra space.

Is Kadane's algorithm dynamic programming?

Yes. It is a one-dimensional DP where dp[i] is the best sum of a subarray ending at index i, with dp[i] = max(nums[i], dp[i-1] + nums[i]). Because each step needs only the previous value, the DP array is reduced to a single variable.

Does Kadane's algorithm work when all numbers are negative?

Yes, if you initialize both the current and best sums with the first element instead of 0. The answer is then the largest (least negative) single element. Initializing with 0 only works when an empty subarray with sum 0 is allowed.

What is the time complexity of Kadane's algorithm?

O(n) time, because it visits each element once, and O(1) extra space, because it stores only two running values. The brute-force alternative is O(n squared) and the divide-and-conquer alternative is O(n log n).

How do you modify Kadane's algorithm for the maximum product subarray?

Track both the largest and the smallest product ending at the current index. When the current number is negative, swap them before updating, because multiplying by a negative turns the smallest product into the largest. This solves LeetCode 152 in O(n) time.

How do you handle a circular array with Kadane's algorithm?

Compute the normal maximum subarray and the minimum subarray in the same pass. A wrapping subarray equals the total sum minus the minimum subarray. Return the larger of the two, unless every number is negative, in which case return the normal maximum.