问题
给出一个圆形整数阵 nums 长度为 n的非空子数组的最大可能之和 。 nums.
循环数组意味着数组的终点与数组的起点相连接。从形式上看,数组的下一个元素 nums[i] 的下一个元素是 nums[(i + 1) % n] 的前一个元素是 nums[i] 是 nums[(i - 1 + *n*) % n].
请注意,原数组的一个索引在结果子数组中不能出现两次。
处理方法
最大的子数组可以有两种情况。子数组要么不是圆形的(只是原数组的一个子数),要么是圆形的(将从起点开始绕过)。
在第一种情况下,使用Kadane的程序来获得最大的子阵列之和。
在第二种情况下,可以找到最小的子数组之和,并且可以从原数组的总和中减少。当然,这将使我们得到剩余子阵列的最大和。
基于以上两种情况,返回最大值。
但还有一种情况是余数。如果所有的元素都是负数,则返回其中最大的一个。
C++编程
#include<bits/stdc++.h>
using namespace std;
int maxSubarraySumCircular(vector<int>& nums) {
int total = accumulate(nums.begin(), nums.end(), 0);
int n = nums.size();
vector<int>nums1=nums;
sort(nums1.begin(), nums1.end());
if(nums1[0]<0 && nums1[n-1]<0){ //if all elements are negative
return nums1[n-1];
}
int sum0 = 0;
int ans0 = 0;
for(int i=0; i<n; i++){ //kadane's algorithm for original array
sum0 += nums[i];
sum0 = max(sum0,0);
ans0 = max(ans0,sum0);
}
for(int i=0; i<n; i++){ //change sign of each number
nums[i]*=-1;
}
int sum = 0;
int ans = 0;
for(int i=0; i<n; i++) //kadane's algorithm after changing signs
{
sum += nums[i];
sum = max(sum,0);
ans = max(ans,sum);
}
return max(total-(-1*ans), ans0);
}
int main(){
vector<int>v{1, 2, -1, 77};
cout<<maxSubarraySumCircular(v);
}
输出
80
C语言编程
#include <stdio.h>
int findMaxSubarray(int a[], int n)
{
int res = 0, sum = 0;
int i;
for (i = 0; i < n; i++) {
sum = sum + a[i];
if (sum < 0)
sum = 0;
if (res < sum)
res = sum;
}
return res;
}
int maxSubarraySum(int a[], int n)
{
//get the maximum sum using standard findMaxSubarray'
int ans0 = findMaxSubarray(a, n);
//find the maximum sum that includes
// corner elements.
int ans = 0, i;
for (i = 0; i < n; i++) {
ans += a[i]; // Calculate array-sum
a[i] = -a[i]; // invert the array (change sign)
}
// max sum with corner elements will be:
// array-sum - (-max subarray sum of inverted array)
ans = ans + findMaxSubarray(a, n);
return (ans > ans0) ? ans : ans0;
}
int main()
{
int a[] = {1, 2, -1, 77};
int n = sizeof(a) / sizeof(a[0]);
printf("Maximum sum is %d",
maxSubarraySum(a, n));
}
输出
Maximum sum is 80
Python编程
def maxSubarray(a):
n = len(a)
ans = 0
sum = 0
for i in range(0, n):
sum = sum + a[i]
if (sum < 0):
sum = 0
if (ans < sum):
ans = sum
return ans
def maxSubarraySumCircular(a):
n = len(a)
# get the maximum sum using standard maxSubarray
ans0 = maxSubarray(a)
# Now find the maximum sum that includes corner
# elements.
ans = 0
for i in range(0, n):
ans += a[i]
a[i] = -a[i]
# Max sum with corner elements will be:
# array-sum - (-max subarray sum of inverted array)
ans = ans + maxSubarray(a)
if ans > ans0:
return ans
else:
return ans0
a = [1,2,-1,77]
print ("Maximum sum is", maxSubarraySumCircular(a))
输出
Maximum sum is 80