跳至主要內容

最大子数组和


最大子数组和

问题

求解最大子数组和(Maximum Subarray Sum):给定一个整数数组,需要找到具有最大和的连续子数组。例如,对于数组[-2, 1, -3, 4, -1, 2, 1, -5, 4],最大子数组和为[4, -1, 2, 1],其和为6。

解题步骤

当我们需要求解一个数组中的最大子数组和时,可以使用分治算法来解决。该算法的基本思路是将数组递归地划分为更小的子数组,然后分别求解左右子数组的最大子数组和。最后,还需要考虑跨越中点的最大子数组和。

具体步骤如下:

  1. 首先,我们将给定的数组划分为两个较小的子数组,分别为左子数组和右子数组。划分的方法是找到数组的中间位置。
  2. 然后,我们递归地求解左子数组和右子数组的最大子数组和。这一步可以通过再次调用分治算法来实现。递归的终止条件是当子数组中只有一个元素时,直接返回该元素。
  3. 接下来,我们需要考虑跨越中点的最大子数组和。我们从中点向左扩展,找到左侧的最大子数组和,然后从中点向右扩展,找到右侧的最大子数组和。这一步是通过线性时间的操作来实现的。
  4. 最后,我们比较左子数组的最大子数组和、右子数组的最大子数组和以及跨越中点的最大子数组和,取其中的最大值作为最终的最大子数组和。

通过不断地递归和合并子数组,我们可以找到整个数组的最大子数组和。这种分治算法的关键在于将问题划分为更小的子问题,并在合并过程中考虑到可能跨越子数组边界的情况。这样可以大大减少问题的规模,提高算法的效率。

题解

public class MaximumSubarraySum {
    public static int findMaxSubarray(int[] arr) {
        return findMaxSubarray(arr, 0, arr.length - 1);
    }

    private static int findMaxSubarray(int[] arr, int low, int high) {
        if (low == high) {
            return arr[low];
        }

        int mid = (low + high) / 2;

        int leftMaxSum = findMaxSubarray(arr, low, mid);
        int rightMaxSum = findMaxSubarray(arr, mid + 1, high);
        int crossMaxSum = findMaxCrossingSubarray(arr, low, mid, high);

        return Math.max(Math.max(leftMaxSum, rightMaxSum), crossMaxSum);
    }

    private static int findMaxCrossingSubarray(int[] arr, int low, int mid, int high) {
        int leftSum = Integer.MIN_VALUE;
        int sum = 0;
        for (int i = mid; i >= low; i--) {
            sum += arr[i];
            leftSum = Math.max(leftSum, sum);
        }

        int rightSum = Integer.MIN_VALUE;
        sum = 0;
        for (int i = mid + 1; i <= high; i++) {
            sum += arr[i];
            rightSum = Math.max(rightSum, sum);
        }

        return leftSum + rightSum;
    }

    public static void main(String[] args) {
        int[] arr = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
        int maxSum = findMaxSubarray(arr);
        System.out.println("Maximum Subarray Sum: " + maxSum);
    }
}
上次编辑于:
贡献者: Neil