解题思路
这是最大子数组和的变种,需要考虑环形的情况。可以通过以下思路解决:
- 环形数组的最大子数组和有两种可能:
- 不跨越边界的普通最大子数组和(使用
算法)
- 跨越边界的最大子数组和(等于总和减去最小子数组和)
- 不跨越边界的普通最大子数组和(使用
- 对于跨越边界的情况:
- 总和减去中间的最小子数组和
- 相当于首尾相连的部分
- 特殊情况:
- 如果所有元素都是负数,返回最大的那个负数
- 如果最小子数组和等于总和,说明所有数都是负数
代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int kadane(vector<int>& nums) {
int maxSum = nums[0];
int currSum = nums[0];
for(int i = 1; i < nums.size(); i++) {
currSum = max(nums[i], currSum + nums[i]);
maxSum = max(maxSum, currSum);
}
return maxSum;
}
int maxCircularSum(vector<int>& nums) {
int n = nums.size();
// 计算普通的最大子数组和
int maxNormal = kadane(nums);
// 如果最大和是负数,说明所有数都是负数
if(maxNormal < 0) return maxNormal;
// 计算总和
int totalSum = 0;
for(int i = 0; i < n; i++) {
totalSum += nums[i];
nums[i] = -nums[i]; // 取反用于计算最小子数组和
}
// 计算环形最大和(总和减去最小子数组和)
int maxCircular = totalSum + kadane(nums);
return max(maxNormal, maxCircular);
}
int main() {
int n;
cin >> n;
vector<int> nums(n);
for(int i = 0; i < n; i++) {
cin >> nums[i];
}
cout << maxCircularSum(nums) << endl;
return 0;
}
import java.util.Scanner;
public class Main {
public static int kadane(int[] nums) {
int maxSum = nums[0];
int currSum = nums[0];
for(int i = 1; i < nums.length; i++) {
currSum = Math.max(nums[i], currSum + nums[i]);
maxSum = Math.max(maxSum, currSum);
}
return maxSum;
}
public static int maxCircularSum(int[] nums) {
int n = nums.length;
// 计算普通的最大子数组和
int maxNormal = kadane(nums);
// 如果最大和是负数,说明所有数都是负数
if(maxNormal < 0) return maxNormal;
// 计算总和
int totalSum = 0;
for(int i = 0; i < n; i++) {
totalSum += nums[i];
nums[i] = -nums[i]; // 取反用于计算最小子数组和
}
// 计算环形最大和(总和减去最小子数组和)
int maxCircular = totalSum + kadane(nums);
return Math.max(maxNormal, maxCircular);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] nums = new int[n];
for(int i = 0; i < n; i++) {
nums[i] = sc.nextInt();
}
System.out.println(maxCircularSum(nums));
sc.close();
}
}
def kadane(nums):
max_sum = nums[0]
curr_sum = nums[0]
for i in range(1, len(nums)):
curr_sum = max(nums[i], curr_sum + nums[i])
max_sum = max(max_sum, curr_sum)
return max_sum
def max_circular_sum(nums):
n = len(nums)
# 计算普通的最大子数组和
max_normal = kadane(nums)
# 如果最大和是负数,说明所有数都是负数
if max_normal < 0:
return max_normal
# 计算总和
total_sum = sum(nums)
# 计算环形最大和(总和减去最小子数组和)
nums = [-x for x in nums] # 取反用于计算最小子数组和
max_circular = total_sum + kadane(nums)
return max(max_normal, max_circular)
n = int(input())
nums = list(map(int, input().split()))
print(max_circular_sum(nums))
算法及复杂度
- 算法:
算法的变种
- 时间复杂度:
,需要遍历数组常数次
- 空间复杂度:
,只使用了常数个变量