Algorithm - Max Sum (Java)
阿新 • • 發佈:2019-01-10
package chimomo.learning.java.algorithm; import java.util.Random; /** * @author Created by Chimomo */ public final class MaxSum { static private int seqStart = 0; static private int seqEnd = -1; private static Random rand = new Random(); /** * Cubic maximum contiguous sub sequence sum algorithm. * seqStart and seqEnd represent the actual best sequence. */ public static int maxSubSum1(int[] a) { int maxSum = 0; for (int i = 0; i < a.length; i++) { for (int j = i; j < a.length; j++) { int thisSum = 0; for (int k = i; k <= j; k++) { thisSum += a[k]; } if (thisSum > maxSum) { maxSum = thisSum; seqStart = i; seqEnd = j; } } } return maxSum; } /** * Quadratic maximum contiguous sub sequence sum algorithm. * seqStart and seqEnd represent the actual best sequence. */ public static int maxSubSum2(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; seqStart = i; seqEnd = j; } } } return maxSum; } /** * Linear-time maximum contiguous sub sequence sum algorithm. * seqStart and seqEnd represent the actual best sequence. */ public static int maxSubSum4(int[] a) { int maxSum = 0; int thisSum = 0; for (int i = 0, j = 0; j < a.length; j++) { thisSum += a[j]; if (thisSum > maxSum) { maxSum = thisSum; seqStart = i; seqEnd = j; } else if (thisSum < 0) { i = j + 1; thisSum = 0; } } return maxSum; } /** * Recursive maximum contiguous sub sequence 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) { int maxLeftBorderSum = 0, maxRightBorderSum = 0; int leftBorderSum = 0, rightBorderSum = 0; int center = (left + right) / 2; // Base case. if (left == right) { return a[left] > 0 ? a[left] : 0; } int maxLeftSum = maxSumRec(a, left, center); int maxRightSum = maxSumRec(a, center + 1, right); for (int i = center; i >= left; i--) { leftBorderSum += a[i]; if (leftBorderSum > maxLeftBorderSum) { maxLeftBorderSum = leftBorderSum; } } for (int i = center + 1; i <= right; i++) { rightBorderSum += a[i]; if (rightBorderSum > maxRightBorderSum) { maxRightBorderSum = rightBorderSum; } } return max3(maxLeftSum, maxRightSum, maxLeftBorderSum + maxRightBorderSum); } /** * Return maximum of three integers. */ private static int max3(int a, int b, int c) { return a > b ? a > c ? a : c : b > c ? b : c; } /** * Driver for divide-and-conquer maximum contiguous sub sequence sum algorithm. */ public static int maxSubSum3(int[] a) { return a.length > 0 ? maxSumRec(a, 0, a.length - 1) : 0; } public static void getTimingInfo(int n, int alg) { int[] test = new int[n]; long startTime = System.currentTimeMillis(); long totalTime = 0; int i; for (i = 0; totalTime < 4000; i++) { for (int j = 0; j < test.length; j++) { test[j] = rand.nextInt(100) - 50; } switch (alg) { case 1: maxSubSum1(test); break; case 2: maxSubSum2(test); break; case 3: maxSubSum3(test); break; case 4: maxSubSum4(test); break; } totalTime = System.currentTimeMillis() - startTime; } System.out.print(String.format("\t%12.6f", (totalTime * 1000 / i) / (double) 1000000)); } /** * Simple test program. */ public static void main(String[] args) { int a[] = {4, -3, 5, -2, -1, 2, 6, -2}; int maxSum; maxSum = maxSubSum1(a); System.out.println("Max sum is " + maxSum + "; it goes" + " from " + seqStart + " to " + seqEnd); maxSum = maxSubSum2(a); System.out.println("Max sum is " + maxSum + "; it goes" + " from " + seqStart + " to " + seqEnd); maxSum = maxSubSum3(a); System.out.println("Max sum is " + maxSum); maxSum = maxSubSum4(a); System.out.println("Max sum is " + maxSum + "; it goes" + " from " + seqStart + " to " + seqEnd); // Get timing info for each algorithm. for (int n = 100; n <= 1000000; n *= 10) { System.out.print(String.format("N = %7d", n)); for (int alg = 1; alg <= 4; alg++) { if (alg == 1 && n > 50000) { System.out.print("\t NA "); continue; } getTimingInfo(n, alg); } System.out.println(); } } } /* Output: Max sum is 11; it goes from 0 to 6 Max sum is 11; it goes from 0 to 6 Max sum is 11 Max sum is 11; it goes from 0 to 6 N = 100 0.000058 0.000003 0.000003 0.000001 N = 1000 0.060757 0.000209 0.000034 0.000014 N = 10000 61.865000 0.019362 0.000366 0.000138 N = 100000 NA 2.005500 0.004207 0.001356 N = 1000000 NA 208.041000 0.042062 0.013916 */