LESSON 28 · INTERMEDIATE4 min read

Maximum Subarray Invariants: Kadane's Algorithm and Circular Buffers

Dissect dynamic programming invariants in continuous array problems, implementing Kadane's algorithm, tracking indices, and solving the maximum circular subarray problem.

OpenJDK 21+ (LTS)Free to readModule 7 of 15
YOUR NEXT SMALL WINS

By the end, you’ll be able to…

  • Formulate the dynamic programming invariant governing Kadane's linear-time maximum subarray algorithm
  • Track start and end subarray indices during Kadane's execution without extra space complexity
  • Solve the maximum circular subarray sum problem using total sum and inverted minimum subarray invariants

01The Invariant Behind Kadane's Algorithm

The Maximum Subarray problem asks for the contiguous subarray within an array of numbers which has the largest sum. A brute-force enumeration of all pairs (i, j) examines O(n^2) subarrays. Precomputing prefix sums reduces the sum query to O(1), but still demands O(n^2) evaluations.

In 1984, Joseph Kadane introduced an optimal O(n) time, O(1) auxiliary space algorithm by identifying a profound local invariant: At any index i, the maximum subarray ending at index i is either the element nums[i] itself, or nums[i] added to the maximum subarray ending at index i - 1.

Mathematically: currentMax[i] = max(nums[i], currentMax[i - 1] + nums[i]). If currentMax[i - 1] drops below zero, adding it to nums[i] would only decrease the sum. Thus, the subarray resets cleanly at index i.

example.js☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.

02Step-by-Step Execution Trace Table

Tracing Kadane's algorithm on an array with mixed positive and negative integers demonstrates the exact transition points where subarrays reset:

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

notes.txtPlain text
+-------+---------+------------+-----------+-----------------------------------+| Index | nums[i] | currentMax | globalMax | Action / Invariant State          |+-------+---------+------------+-----------+-----------------------------------+| 0     | -2      | -2         | -2        | Initialized at index 0            || 1     | 1       | 1          | 1         | Reset: 1 > (-2 + 1)               || 2     | -3      | -2         | 1         | Extended: 1 + (-3) = -2           || 3     | 4       | 4          | 4         | Reset: 4 > (-2 + 4)               || 4     | -1      | 3          | 4         | Extended: 4 + (-1) = 3            || 5     | 2       | 5          | 5         | Extended: 3 + 2 = 5 (New Max!)    || 6     | 1       | 6          | 6         | Extended: 5 + 1 = 6 (Global Max!) || 7     | -5      | 1          | 6         | Extended: 6 + (-5) = 1            || 8     | 4       | 5          | 6         | Extended: 1 + 4 = 5               |+-------+---------+------------+-----------+-----------------------------------+Result: Global Maximum Subarray Sum = 6 (Subarray: [4, -1, 2, 1])

03Tracking Subarray Boundary Indices

In production scenarios—such as finding the period of peak network throughput or financial trading profit—knowing the sum alone is insufficient. We must report the exact start and end indices of the winning subarray.

We maintain a tempStart pointer that updates whenever currentMax resets to nums[i]. Whenever currentMax exceeds globalMax, we lock in start = tempStart and end = i. This keeps space complexity strictly O(1) while providing full boundary reporting.

example.js☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.

04The Maximum Circular Subarray Problem

In a circular array, a subarray can wrap around the end to the beginning. There are two structural possibilities for the maximum circular sum: Case 1: The maximum subarray does not wrap around (solved directly by standard Kadane). Case 2: The maximum subarray wraps around.

Notice that if the subarray wraps around, the elements not included in the circular subarray form a contiguous MINIMUM subarray in the middle! Therefore: MaxCircularSum = TotalSum - MinSubarraySum.

The overall answer is max(StandardMaxKadane, TotalSum - MinKadane). One crucial edge case exists: if all elements in the array are negative, TotalSum - MinKadane equals 0 (representing an empty array), so we must return StandardMaxKadane directly.

05Production Architecture & Engineering Trade-Offs

Algorithmic efficiency in real-world software is heavily influenced by CPU hardware architecture, specifically the L1, L2, and L3 cache hierarchies and hardware branch predictors. While an algorithm may exhibit an optimal theoretical asymptotic complexity like O(n), poor spatial locality caused by pointer chasing across fragmented memory blocks can make it perform slower than a theoretically inferior algorithm operating over contiguous array memory.

When implementing two pointers and sliding window routines, developers must maintain strict boundary invariants to eliminate off-by-one errors and avoid redundant recomputations. Precomputing prefix sums or maintaining monotonic tracking queues transforms polynomial search operations into deterministic linear scans that execute with minimal memory allocations.

LET IT CLICK

The ideas worth keeping.

  • Kadane's algorithm solves the maximum contiguous subarray problem in O(n) time and O(1) space.
  • Subarray start and end indices can be captured without allocating extra memory by recording reset points.
  • Circular subarray problems reduce to max(KadaneMax, TotalSum - KadaneMin) with an all-negative guard.
TURN UNDERSTANDING INTO SOMETHING YOU CAN DO

Make it yours.

Type and test your code right here in the interactive workspace. Run your solution, check the output, and compare with the worked guide when ready.

01

Exercise 1: Implement a function that computes the minimu

Implement a function that computes the minimum subarray sum in O(n) time and O(1) space using an inverted Kadane invariant.

your_turn_1.java☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.
Explore a worked solution
one_possible_solution.javaJava
public class MinSubarray {    public static int minSubArray(int[] nums) {        int currentMin = nums[0];        int globalMin = nums[0];        for (int i = 1; i < nums.length; i++) {            currentMin = Math.min(nums[i], currentMin + nums[i]);            globalMin = Math.min(globalMin, currentMin);        }        return globalMin;    }}

Replace Math.max with Math.min to find the contiguous subarray with the smallest possible sum.

02

Exercise 2: Explain how to handle the edge case in Maximu

Explain how to handle the edge case in Maximum Circular Subarray when the array contains only negative numbers like [-3, -2, -3].

your_turn_2.java☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.
Explore a worked solution
one_possible_solution.javaJava
// If all numbers are negative, standard max Kadane returns the least negative number (e.g. -2).// Meanwhile, min Kadane encompasses the entire array, so totalSum == minSum.// Thus, totalSum - minSum = 0, which corresponds to an invalid empty subarray.// Guard condition: if (maxKadane < 0) return maxKadane; else return Math.max(maxKadane, totalSum - minKadane);

Check whether maxKadane is negative before computing totalSum - minKadane.

A SMALL QUESTION. A USEFUL NEXT STEP.

What stayed with you?

Check the ideas while they’re fresh. Your answers stay in this page and feedback appears as you go.

A LITTLE ACTIVE RECALL0 / 3 answered
01What is the time and space complexity of Kadane's algorithm?
02When does Kadane's algorithm reset currentMax to start a new subarray?
03How is the wrapped maximum subarray calculated in the circular subarray problem?
⚡CODING CHALLENGE
🔒Required to Mark Lesson Complete

Exercise 1: Implement a function that computes the minimu

Implement a function that computes the minimum subarray sum in O(n) time and O(1) space using an inverted Kadane invariant.

EXPECTED OUTPUT
Build successful. (Java 15)
[Process exited normally]
Main.javaJava
Ctrl + ↵
Execution Console
Click "Run & Verify" (or press Ctrl + Enter) to test your code against the challenge.

Keep exploring.

The official references behind this lesson, when you want a second angle or the full details.

MODULE 07 · PRACTICAL SELF-CHECK

Pause. Put the pieces together.

You’ve reached the end of Array Algorithms: Prefix Sums, Two Pointers & Sliding Window. Before moving on, use this task to check what you can do independently.

Solve sliding window substring problems and circular maximum subarray problems in linear time.

Try it in your own environment and write down the result. This is a self-check; reading completion does not evaluate your code.

Review this module

One lesson closer.

Reading is a start. Trying it yourself makes the connection.

Solve the hands-on coding challenge in the knowledge section to verify your code and unlock lesson completion.