Maximum Sum Circular Subarray
Problem
nums that is treated as a ring: the
element after the last one is the first one again. Return the largest possible sum of a
non-empty contiguous piece of this ring, where each position may be used at most
once (a piece can wrap around the end, but cannot be longer than n).[1,-2,3,-2]Output3[5,-3,5]Output10 (wraps: 5 + 5)[-3,-2,-3]Output-21 ≤ n ≤ 3·104 · -3·104 ≤ nums[i] ≤ 3·104
Try it yourself
class Solution {
public int maxSubarraySumCircular(int[] nums) {
}
}
total − minimum subarray sum; run
Kadane twice (max and min) and take the better answer.Instinct Best sum or product of a contiguous subarray in one pass? At each index choose - extend the run ending here or restart - and track the global best.
Memory hack Carry the bag only while it helps - a negative past is dead weight, drop it and restart here.
Open the Kadane's Running Best guide →Approaches
Brute ForceTry Every Start and Length
O(n²)Space O(1)Fix a starting index, then grow the piece one step at a time for up to
n elements, reading nums[(start + len) % n]. The running sum
is extended in O(1), so every one of the n² pieces is scored.
public int maxSubarraySumCircular(int[] nums) { int n = nums.length; int best = Integer.MIN_VALUE; for (int start = 0; start < n; start++) { int sum = 0; // grow the piece clockwise, at most n elements for (int len = 0; len < n; len++) { sum += nums[(start + len) % n]; best = Math.max(best, sum); } } return best; }
Correct and simple, but quadratic — too slow at n = 3·104 in tight limits.
BetterKadane + Best Prefix / Suffix Split
O(n)Space O(n)A wrapping piece is a suffix nums[j..n-1] glued to a
prefix nums[0..i] with i < j. Precompute
bestPrefix[i] = max prefix sum ending at or before i, then
sweep suffixes from the right and pair each with bestPrefix[j-1].
Compare with plain Kadane for the non-wrapping case.
public int maxSubarraySumCircular(int[] nums) { int n = nums.length; // non-wrapping case: classic Kadane int best = nums[0], cur = 0; for (int x : nums) { cur = Math.max(cur + x, x); best = Math.max(best, cur); } // bestPrefix[i] = max sum of nums[0..k] over all k <= i int[] bestPrefix = new int[n]; int run = nums[0]; bestPrefix[0] = run; for (int i = 1; i < n; i++) { run += nums[i]; bestPrefix[i] = Math.max(bestPrefix[i - 1], run); } // wrapping case: suffix nums[j..n-1] + best prefix ending before j int suffix = 0; for (int j = n - 1; j >= 1; j--) { suffix += nums[j]; best = Math.max(best, suffix + bestPrefix[j - 1]); } return best; }
Linear time, but needs an extra O(n) array.
OptimalDouble Kadane (Total − Min Subarray)
O(n)Space O(1)In one pass track the usual max-subarray sum and the min-subarray sum
plus the total. Removing the worst middle piece leaves the best wrapping piece:
total − minSum. If every number is negative, that would remove
everything (an empty piece), so return maxSum instead.
public int maxSubarraySumCircular(int[] nums) { int total = 0; int curMax = 0, maxSum = nums[0]; int curMin = 0, minSum = nums[0]; for (int x : nums) { curMax = Math.max(curMax + x, x); maxSum = Math.max(maxSum, curMax); curMin = Math.min(curMin + x, x); minSum = Math.min(minSum, curMin); total += x; } // all negative: total - minSum would be the empty piece if (maxSum < 0) return maxSum; return Math.max(maxSum, total - minSum); }
Dry run[1,-2,3,-2]
- i=05i-35max=5 min=5 tot=5
- i=15-3i5max=5 min=-3 tot=2
- i=25-35imax=7 min=-3 tot=7
- end5-35max(7, 7-(-3)) = 10
One pass, constant memory — the standard interview answer.
At a glance
| Level | Approach | Time | Space |
|---|---|---|---|
| Brute Force | Try Every Start and Length | O(n²) | O(1) |
| Better | Kadane + Best Prefix / Suffix Split | O(n) | O(n) |
| Optimal | Double Kadane (Total − Min Subarray) | O(n) | O(1) |
- Returning
total − minSumwhen all numbers are negative — that is the empty piece (0). - Concatenating the array and running Kadane — allows pieces longer than
n. - Initialising
maxSumto 0 — wrong for all-negative input.
- Split the cases: the answer either wraps or it doesn’t.
- Draw the ring: a wrapping piece is the complement of a middle piece.
- Mention the prefix/suffix version as a stepping stone if the complement trick doesn’t click.