最大子序列

 

package alg;



/**

 * 求取最大的子数列

 * */



public class SubMaxArray {



    public static void main(String[] args) {

        int[] a = new int[] { 1, -2, 3, 10, -4, 7, 2, -5 };

        int[] b = new int[] { -6, 2, 4, -7, 5, 3, 2, -1, 6, -9, 10, -2 };

        int max = maxSum(a, a.length);

        System.out.println(max);



        int maxb = maxSum(b, b.length);

        System.out.println(maxb);

        

        long wmax = maxSubSum4(a);

        System.out.println(wmax);



        long malxb = maxSubSum4(b);

        System.out.println(malxb);

    }



    // 暴力的循环

    static int maxSum(int[] A, int n) {

        int maximum = Integer.MIN_VALUE;

        int sum = 0;

        for (int i = 0; i < n; i++) {

            for (int j = i; j < n; j++) {

                for (int k = i; k <= j; k++) {

                    sum += A[k];

                }

                if (sum > maximum) {

                    maximum = sum;

                }

                sum = 0; // 这里要记得清零,否则的话sum最终存放的是所有子数组的和。

            }

        }

        return maximum;

    }



    // 省略重复的计算

    static int maxSumModify(int[] a) {

        int maxSum = 0;

        for (int i = 0; i < a.length; i++) {

            int thisSum = 0;

            for (int j = i; j < a.length; j++) {

                thisSum += a[j];

                if (thisSum > maxSum)

                    maxSum = thisSum;

            }

        }

        return maxSum;

    }



    /**

     * 分治算法 最大的子数列,在前半部分,在后半部分 或者从中间进行计算

     * */

    static long maxSumRec(int[] a, int left, int right) {

        if (left == right) {

            if (a[left] > 0)

                return a[left];

            else

                return 0;

        }

        int center = (left + right) / 2;

        long maxLeftSum = maxSumRec(a, left, center);

        long maxRightSum = maxSumRec(a, center + 1, right);



        // 求出以左边对后一个数字结尾的序列最大值

        long maxLeftBorderSum = 0, leftBorderSum = 0;

        for (int i = center; i >= left; i--) {

            leftBorderSum += a[i];

            if (leftBorderSum > maxLeftBorderSum)

                maxLeftBorderSum = leftBorderSum;

        }



        // 求出以右边对后一个数字结尾的序列最大值

        long maxRightBorderSum = 0, rightBorderSum = 0;

        for (int j = center + 1; j <= right; j++) {

            rightBorderSum += a[j];

            if (rightBorderSum > maxRightBorderSum)

                maxRightBorderSum = rightBorderSum;

        }



        return max3(maxLeftSum, maxRightSum, maxLeftBorderSum

                + maxRightBorderSum);

    }



    static long maxSubSum3(int[] a) {

        return maxSumRec(a, 0, a.length - 1);

    }



    static long max3(long a, long b, long c) {

        if (a < b) {

            a = b;

        }

        if (a > c)

            return a;

        else

            return c;

    }



    // 线性的算法O(N)

    /**

     * 算法的基础:如果a[i] 为负数,那么他不可能是最大子序列的开始,推论是最大子数列的开头的数组的和不可能是一个负数,

     * 也就是说为负数的子序列不可能是最大子序列的开始。

     * */

    static long maxSubSum4(int[] a) {

        long maxSum = 0, thisSum = 0;

        for (int j = 0; j < a.length; j++) {

            thisSum += a[j];

            if (thisSum > maxSum)

                maxSum = thisSum;

            else if (thisSum < 0)

                thisSum = 0;

        }

        return maxSum;

    }



    /**

     * 如果全部为负数的情况下,最大的子序列是为一个元素都没有的零,

     * 还是最大的负数?

     * */

    static int maxsum(int[] a)

    {

        int max = a[0]; // 全负情况,返回最大数

        int sum = 0;

        for (int j = 0; j < a.length; j++) {

            if (sum >= 0){ // 如果加上某个元素,sum>=0的话,就加

                sum += a[j];

            }else{

                sum = a[j]; // 如果加上某个元素,sum<0了,就不加

            }

            if (sum > max)

                max = sum;

        }

        return max;

    }

}

你可能感兴趣的:(序列)