环形整数数组的最大子数组和| 豆包MarsCode AI刷题

62 阅读3分钟

问题描述

给定一个长度为 n 的环形整数数组 nums,我们需要找到这个数组中的非空子数组的最大可能和。环形数组意味着数组的首尾相连,即 nums[i] 的下一个元素是 nums[(i + 1) % n],而 nums[i] 的前一个元素是 nums[(i - 1 + n) % n]。需要注意的是,每个元素最多只能在子数组中出现一次,且子数组是连续的,可以跨越数组的末端连接到开头。

输入输出

  • 输入:一个整数数组 nums。
  • 输出:一个整数,表示环形数组中非空子数组的最大和。

算法思路

  1. 非环形数组的最大子数组和:首先,我们需要计算非环形数组的最大子数组和。这可以通过 Kadane 算法实现,该算法可以找出数组中连续子数组的最大和。

  2. 环形数组的最大子数组和:对于环形数组,我们考虑两种情况:

    • 包含整个数组的子数组。
    • 不包含整个数组的子数组,即至少跳过数组中的一个元素。

    为了计算环形数组的最大子数组和,我们可以将数组中的每个元素取反,然后再次应用 Kadane 算法。这样做的原因是,如果我们取反数组中的元素,那么原本的最小子数组和就变成了最大子数组和。然后,我们将原始数组的总和与取反后数组的最大子数组和相加,得到的结果就是环形数组的最大子数组和。

  3. 特殊情况处理:如果环形数组的最大子数组和为0,说明所有元素都是负数,此时我们应该返回非环形数组的最大子数组和。

代码实现

    public static int solution(int[] nums) {
        int n = nums.length;
        if (n == 0) return 0;
        
        // 计算非环形数组的最大子数组和
        int maxSum = kadane(nums);
        
        // 计算环形数组的最大子数组和
        int totalSum = 0;
        for (int i = 0; i < n; i++) {
            totalSum += nums[i];
            nums[i] = -nums[i]; // 反转数组元素
        }
        
        int minSum = kadane(nums); // 计算反转数组的最大子数组和
        int maxCircularSum = totalSum + minSum; // 环形数组的最大子数组和
        
        // 如果环形数组的最大子数组和为0,说明所有元素都是负数,返回非环形数组的最大子数组和
        return maxCircularSum > 0 ? Math.max(maxSum, maxCircularSum) : maxSum;
    }

    private static int kadane(int[] nums) {
        int maxEndingHere = nums[0];
        int maxSoFar = nums[0];
        
        for (int i = 1; i < nums.length; i++) {
            maxEndingHere = Math.max(nums[i], maxEndingHere + nums[i]);
            maxSoFar = Math.max(maxSoFar, maxEndingHere);
        }
        
        return maxSoFar;
    }

    public static void main(String[] args) {
        System.out.println(solution(new int[]{-1, -2, 3, -2}) == 3);
        System.out.println(solution(new int[]{-5, -3, 5}) == 5);
        System.out.println(solution(new int[]{-3, -1, 2, -1}) == 2);
        System.out.println(solution(new int[]{-2, -3, -1}) == -1);
    }
}

代码中定义了两个方法:

  • kadane:实现 Kadane 算法,用于计算非环形数组的最大子数组和。
  • solution:实现上述算法思路,计算环形数组的最大子数组和。

测试样例

代码中提供了四个测试样例,分别对应不同的输入数组,并验证了算法的正确性。

总结

这个问题考察了对 Kadane 算法的理解和应用,以及如何处理环形数组的特殊性质。通过反转数组元素的技巧,我们可以将问题转化为求解非环形数组的最大子数组和问题,从而简化问题的解决过程。