解题思路

这是最大子数组和的变种,需要考虑环形的情况。可以通过以下思路解决:

  1. 环形数组的最大子数组和有两种可能:
    • 不跨越边界的普通最大子数组和(使用 算法)
    • 跨越边界的最大子数组和(等于总和减去最小子数组和)
  2. 对于跨越边界的情况:
    • 总和减去中间的最小子数组和
    • 相当于首尾相连的部分
  3. 特殊情况:
    • 如果所有元素都是负数,返回最大的那个负数
    • 如果最小子数组和等于总和,说明所有数都是负数

代码

#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))

算法及复杂度

  • 算法: 算法的变种
  • 时间复杂度:,需要遍历数组常数次
  • 空间复杂度:,只使用了常数个变量