Largest Sum Subarray in a Circular Array
Solve this Problemnums — where the last element connects back around to the first — return the largest possible sum of any non-empty contiguous subarray, allowing the subarray to wrap past the end of the array and continue from the beginning.
Trying every wrapped window works, but re-summing each one from scratch wastes the structure of the problem. Every wrap-around subarray is the complement of some ordinary, non-wrapping subarray sitting in the middle — so the best wrap-around sum is just total - (the minimum-sum subarray). Running Kadane's algorithmKadane's AlgorithmA single O(n) pass that finds the maximum-sum contiguous subarray by tracking a running "best streak ending here," resetting it to the current element whenever extending the previous streak would hurt rather than help. twice — once for the maximum, once for the minimum — turns an O(n²) search into a single O(n) pass.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ nums.length ≤ 3×10⁴ - ◆
-3×10⁴ ≤ nums[i] ≤ 3×10⁴
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
| 1 | class Solution { |
| 2 | public int maxCircularSubarraySum(int[] nums) { |
| 3 | int total = 0, maxSum = nums[0], curMax = 0, minSum = nums[0], curMin = 0; |
| 4 | for (int num : nums) { |
| 5 | curMax = Math.max(curMax + num, num); |
| 6 | maxSum = Math.max(maxSum, curMax); |
| 7 | curMin = Math.min(curMin + num, num); |
| 8 | minSum = Math.min(minSum, curMin); |
| 9 | total += num; |
| 10 | } |
| 11 | if (maxSum < 0) return maxSum; |
| 12 | return Math.max(maxSum, total - minSum); |
| 13 | } |
| 14 | } |
| 15 |
05050Start total at 0, maxSum and minSum at nums[0] = 5, and curMax/curMin at 0. Walk the array once, running Kadane's algorithm for both the maximum and minimum subarray sum at the same time.
Approach & Solutions
Brute Force
BruteTreat the array as circular by using modulo arithmetic: for every possible start index and every possible length up to n, sum that window (wrapping around the end if needed) and track the best sum seen. Correct, but every window is summed from scratch even though consecutive windows barely differ.
O(n²)O(1)1class Solution {
2 public int maxCircularSubarraySum(int[] nums) {
3 int n = nums.length;
4 int maxSum = nums[0];
5 for (int i = 0; i < n; i++) {
6 int sum = 0;
7 for (int len = 1; len <= n; len++) {
8 sum += nums[(i + len - 1) % n];
9 maxSum = Math.max(maxSum, sum);
10 }
11 }
12 return maxSum;
13 }
14}Optimal — Kadane's Algorithm, Twice
OptimalThere are only two cases for where the best circular subarray can sit. Either it doesn't wrap around — that's the ordinary Kadane's algorithm answer (maxSum). Or it DOES wrap around, which means the elements it skips form a single contiguous block in the middle — so the wrap-around sum is just the array's total minus that middle block's sum, and making the skipped block as negative as possible (a second Kadane's pass tracking the minimum) maximizes what's left. The one exception: if every element is negative, an empty wrap-around selection isn't valid, so just return maxSum directly.
O(n)O(1)1class Solution {
2 public int maxCircularSubarraySum(int[] nums) {
3 int total = 0, maxSum = nums[0], curMax = 0, minSum = nums[0], curMin = 0;
4 for (int num : nums) {
5 curMax = Math.max(curMax + num, num);
6 maxSum = Math.max(maxSum, curMax);
7 curMin = Math.min(curMin + num, num);
8 minSum = Math.min(minSum, curMin);
9 total += num;
10 }
11 if (maxSum < 0) return maxSum;
12 return Math.max(maxSum, total - minSum);
13 }
14}