算法--分治算法之最大子序列求和问题

分治算法(divide and conquer)

分治算法由两部分组成:

1.分(divide):递归将一个大的问题分解为2个或2个以上的相同小问题并对子问题求解。

2.治(conquer): 从若干个子问题的解构建原问题的解。

使用分治法时应注意以下两点:

1.将一个大的问题分解成为若干小问题时应该是相同的若干小问题。

2.分解的若干子问题中,不应该包含其它子问题。也就是不要在若干个子问题中去求一个或多个想同的子问题的解。若算法中存在这样的问题时间效率将大幅度下降。

最大子序列求和例子:

import java.util.Random;
import java.util.Scanner;

/**
 * 分治算法--最大子序列求和问题
 *
 * @分(divide):递归解决较小的问题
 * @治(conquer):然后从子问题的解构建原问题的解
 * @说明:一般坚持子问题是不相交的(即基本上不重叠)
 * @author lls
 *
 */
public class DivideAndConquerAlgorithm {

    public static void main(String[] args) {
        init();// 数据初始化
    }

    private static void init() {
        Scanner sc = new Scanner(System.in);
        Random rand = new Random();
        int n = sc.nextInt();
        int[] array = new int[n];
        for (int i = 0; i < n; i++) {
            array[i] = rand.nextInt(10) - rand.nextInt(10);
            System.out.print(array[i] + "   ");
        }
        System.out.println();
        System.out.println("maxSubSum3=" + maxSubSum3(array));
        System.out.println("maxSubSum4=" + maxSubSum4(array));
        sc.close();
    }
    /**
     * 本算法是为一个更为简单有效的求解最大子序列和的方法
     * 时间效率为0(n)
     */
    public static int maxSubSum4(int[] a) {
        int 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;
    }

    /**
     * Driver for divide-and-conquer maximum contiguous subsequence sum algorithm.
     */
    public static int maxSubSum3(int[] a) {
        return maxSumRec(a, 0, a.length - 1);
    }

    /**
     * Recursive maximum contiguous subsequence sum algorithm.
     * Finds maximum sum in subarray spanning a[left....right].
     * Does not attempt to maintain actual best sequence.
     */
    private static int maxSumRec(int[] a, int left, int right) {
        if (left == right) // Base case
            if (a[left] > 0)
                return a[left];
            else
                return 0;

        int center = (left + right) / 2;
        int maxLeftSum = maxSumRec(a, left, center);
        int maxRightSum = maxSumRec(a, center + 1, right);

        int maxLeftBorderSum = 0, leftBorderSum = 0;
        for (int i = center; i >= left; i--) {
            leftBorderSum += a[i];
            if (leftBorderSum > maxLeftBorderSum)
                maxLeftBorderSum = leftBorderSum;
        }

        int maxRightBorderSum = 0, rightBorderSum = 0;
        for (int i = center + 1; i <= right; i++) {
            rightBorderSum += a[i];
            if (rightBorderSum > maxRightBorderSum)
                maxRightBorderSum = rightBorderSum;
        }
        return max3(maxLeftSum, maxRightSum, maxLeftBorderSum + maxRightBorderSum);
    }

    /**
     * return the biggest of arrayList.
     */
    private static int max3(int a, int b, int c) {
        int max = a;
        if (b > max)
            max = b;
        if (c > max)
            max = c;
        return max;
    }

}


猜你喜欢

转载自blog.csdn.net/Mr_lilongsha/article/details/80356287