算法笔记:最大子数组

一、分治法

将数组分为左右两部分,那么最大子数组存在三种可能。

  • 位于左边的子数组
  • 位于右边的子数组
  • 为左子数组的最大后缀与右子数组的最大前缀之和

二、动态规划

如果当前最大数组和为负数,那么加上下一个数的和必然小于下一个的本身。所以当最大数组和为负数时,直接舍弃。

其状态转移方程为sum[i] = max(arr[i], sum[i - 1] + arr[i])

三、实现

public class Solution {
    public static int maxSubSlow(int[] array) {
        int result = Integer.MIN_VALUE;
        for (int i = 0; i < array.length; i++) {
            int t = 0;
            for (int j = i; j < array.length; j++) {
                t += array[j];
                if (t > result)
                    result = t;
            }
        }
        return result;
    }

    private static int crossSub(int[] array, int min, int mid, int max) {
        int leftResult = array[mid];
        for (int i = mid, t = 0; i >= min; i--) {
            t += array[i];
            if (t > leftResult)
                leftResult = t;
        }

        int rightResult = array[mid + 1];
        for (int i = mid + 1, t = 0; i <= max; i++) {
            t += array[i];
            if (t > rightResult)
                rightResult = t;
        }

        return Math.max(leftResult, rightResult);
    }

    public static int maxSubDC(int[] array, int min, int max) {
        if (min == max)
            return array[min];
        int mid = (max + min) / 2;

        int leftMax = maxSubDC(array, min, mid);
        int rightMax = maxSubDC(array, mid + 1, max);
        int crossMax = crossSub(array, min, mid, max);

        return Math.max(crossMax, Math.max(leftMax, rightMax));
    }

    public static int maxSubDP(int[] array) {
        int result = Integer.MIN_VALUE;
        for (int i = 0, t = 0; i < array.length; i++) {
            t += array[i];
            if (t > result)
                result = t;
            if (t < 0)
                t = 0;
        }
        return result;
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/arseneyao/p/9023404.html