Given a circular integer arraynums of length n, return the maximum possible sum of a non-empty subarray ofnums.
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.
Method 1 - Using Kadane for Max and Min Sum Subarray and Total Sum#
So there are two case:
Case 1. The first is that the subarray take only a middle part, and we know how to find the max subarray sum using Maximum Subarray Sum.
Case2. The second is that the subarray take a part of head array and a part of tail array. Inversion: If max subarray occurs at ends, then min subarray occurs in the middle. So we just need to find the smallest one in the middle, the use totalSum - minSum can the the possible answer. Also, to calculate minSum, while calculating maxSum. Look at the code below.
Just one to pay attention:
If all numbers are negative, maxSum = max(A) and minSum = sum(A).
In this case, max(maxSum, total - minSum) = 0, which means the sum of an empty subarray.
According to the deacription, We need to return the max(A), instead of sum of am empty subarray.
So we return the maxSum to handle this corner case.
We can apply Kadane’s algorithm similar to Maximum Sum Subarray. Here is the approach:
Find the total sum of the array.
Find the minimum subarray sum using Kadane’s algorithm (by inverting the signs of the array elements and running Kadane’s algorithm).
The maximum subarray sum in the circular case can be found by taking the total sum and subtracting the minimum subarray sum.
The maximum sum is the greater of the result from the non-circular case and the circular case, unless all elements are negative (in which case, the result from the non-circular case is used).
publicclassSolution {
publicintmaxSubarraySumCircular(int[] nums) {
int n = nums.length;
// Finding the non-circular maximum subarray sum using Kadane's algorithmint maxKadane = kadane(nums);
// Calculating the total sum and inverting the elementsint totalSum = 0;
for (int i = 0; i < n; i++) {
totalSum += nums[i];
nums[i]=-nums[i];
}
// Finding the minimum subarray sum by using Kadane's algorithm on the inverted arrayint maxInvertedKadane = kadane(nums);
// Restoring the original array elementsfor (int i = 0; i < n; i++) {
nums[i]=-nums[i];
}
int maxCircular = totalSum + maxInvertedKadane; // Inverted Kadane gives minimum sum, re-invert it// If all numbers are negative, maxCircular would be zero which we need to avoidif (maxCircular == 0) return maxKadane;
// The result is the maximum of the two sumsreturn Math.max(maxKadane, maxCircular);
}
privateintkadane(int[] nums) {
int currentMax = nums[0];
int globalMax = nums[0];
for (int i = 1; i < nums.length; i++) {
currentMax = Math.max(nums[i], currentMax + nums[i]);
if (currentMax > globalMax) {
globalMax = currentMax;
}
}
return globalMax;
}
}
classSolution:
defmaxSubarraySumCircular(self, nums: List[int]) -> int:
# Finding the non-circular maximum subarray sum using Kadane's algorithmdefkadane(nums: List[int]) -> int:
current_max = nums[0]
global_max = nums[0]
for num in nums[1:]:
current_max = max(num, current_max + num)
if current_max > global_max:
global_max = current_max
return global_max
total_sum = sum(nums)
max_kadane = kadane(nums) # Non-circular maximum subarray sum# Invert the elements of the array to find the minimum subarray sumfor i in range(len(nums)):
nums[i] =-nums[i]
max_inverted_kadane = kadane(nums)
# Restore the original array elementsfor i in range(len(nums)):
nums[i] =-nums[i]
max_circular = total_sum + max_inverted_kadane # Inverted Kadane gives minimum sum, re-invert it# Special case: if all elements are negative, max_circular would be zero which is incorrectif max_circular ==0:
return max_kadane
return max(max_kadane, max_circular)