You are given a circular integer array nums of length n, return the maximum possible sum of a non-empty subarray of nums.
A circular array means the end of the array connects to the beginning of the array. Formally, the next element of nums[i] is nums[(i + 1) % n] and the previous element of nums[i] is nums[(i - 1 + n) % n].
A subarray may only include each element of the fixed buffer nums at most once. Formally, for a subarray nums[i], nums[i + 1], ..., nums[j], there does not exist i <= k1, k2 <= j with k1 % n == k2 % n.
Example 1:
Input: nums = [-2,4,-5,4,-5,9,4]
Output: 15Explanation: Subarray [-2,4,9,4] has maximum sum 15.
Example 2:
Input: nums = [2,3,-4]
Output: 5Constraints:
n == nums.length1 <= n <= 3 * 10,000-30,000 <= nums[i] <= 30,000Before attempting this problem, you should be comfortable with:
Since the array is circular, any contiguous subarray can wrap around from the end back to the beginning. The most direct approach is to try every possible starting position and extend the subarray up to the full length of the array, tracking the maximum sum found. Using modular indexing allows us to wrap around seamlessly. While simple to understand, this method is slow because it examines every possible subarray.
res with the first element.i from 0 to n - 1:cur_sum to 0.i up to i + n - 1, using j % n to wrap around.cur_sum and update res with the maximum.res.A circular subarray with maximum sum either lies entirely within the array (no wrap), or it wraps around (takes a prefix and a suffix). For the non-wrapping case, we can use standard Kadane's algorithm. For the wrapping case, we want the best prefix ending at some index combined with the best suffix starting after that index. By precomputing the maximum suffix sum from each position, we can efficiently find the best combination of prefix and suffix sums in a single pass.
right_max[i] as the maximum suffix sum starting at index i or later, iterating from right to left.max_sum with nums[0], and set cur_max and prefix_sum to 0.cur_max using Kadane's logic: cur_max = max(cur_max, 0) + nums[i].max_sum with cur_max (non-wrapping case).nums[i] to prefix_sum.i + 1 < n, update max_sum with prefix_sum + right_max[i + 1] (wrapping case).max_sum.class Solution:
def maxSubarraySumCircular(self, nums: List[int]) -> int:
n = len(nums)
right_max = [0] * n
right_max[-1] = nums[-1]
suffix_sum = nums[-1]
for i in range(n - 2, -1, -1):
suffix_sum += nums[i]
right_max[i] = max(right_max[i + 1], suffix_sum)
max_sum = nums[0]
cur_max = 0
prefix_sum = 0
for i in range(n):
cur_max = max(cur_max, 0) + nums[i]
max_sum = max(max_sum, cur_max)
prefix_sum += nums[i]
if i + 1 < n:
max_sum = max(max_sum, prefix_sum + right_max[i + 1])
return max_sumThe maximum circular subarray sum falls into one of two cases: either the subarray does not wrap around, or it does. For the non-wrapping case, standard Kadane's algorithm finds the maximum subarray sum. For the wrapping case, if we remove a contiguous middle portion from the array, what remains is a prefix plus a suffix. Removing the minimum subarray sum leaves behind the maximum wrapping sum, which equals total - minSubarraySum. We take the better of these two cases, but if all elements are negative, the maximum is simply the largest single element.
globMax and globMin to nums[0], and set curMax, curMin, and total to 0.num in nums:curMax = max(curMax + num, num) and globMax = max(globMax, curMax).curMin = min(curMin + num, num) and globMin = min(globMin, curMin).num to total.globMax > 0, return max(globMax, total - globMin). Otherwise, return globMax.class Solution:
def maxSubarraySumCircular(self, nums: List[int]) -> int:
globMax, globMin = nums[0], nums[0]
curMax, curMin = 0, 0
total = 0
for num in nums:
curMax = max(curMax + num, num)
curMin = min(curMin + num, num)
total += num
globMax = max(globMax, curMax)
globMin = min(globMin, curMin)
return max(globMax, total - globMin) if globMax > 0 else globMaxWhen all elements are negative, the minimum subarray equals the entire array, so total - minSum becomes zero. This would incorrectly suggest an empty subarray. The fix is to check if maxSum > 0 before considering the wrap-around case, or equivalently return maxSum when all elements are negative.
A common mistake is trying to directly find the maximum wrap-around subarray. The key insight is that if a subarray wraps around, it means we are excluding a contiguous middle portion. Therefore, the wrap-around max equals total - minSubarraySum. Failing to realize this leads to overly complicated solutions.
Initializing curMax and curMin to nums[0] instead of 0 can cause off-by-one errors when updating the global max/min. The standard Kadane approach resets the running sum when it becomes detrimental, which requires careful initialization to avoid skipping or double-counting the first element.
Sign in to join the discussion