// Helene Martin, CSE 143 // Times the execution of three different algorithms for calculating the maximum // subsequence sum of an array of values. // With algorithm 1, 5000 elements takes significant time. // With algorithm 3, we can barely time 1,000,000 elements // The right algorithm can make a huge difference. import java.util.Random; import java.util.Scanner; public class MaxSum { public static void main(String[] args) { Scanner console = new Scanner(System.in); System.out.print("Input size (n): "); int n = console.nextInt(); System.out.print("Algorithm: "); int algorithm = console.nextInt(); // trial runs to avoid Java optimizations findMax(algorithm, new int[n]); findMax(algorithm, new int[2 * n]); findMax(algorithm, new int[3 * n]); // timed tests on inputs of size n, 2n and 3n double time1 = timingTest(algorithm, n); double time2 = timingTest(algorithm, 2 * n); double time3 = timingTest(algorithm, 3 * n); System.out.println("Double/single ratio = " + time2 / time1); System.out.println("Triple/single ratio = " + time3 / time1); } // Calculates the maximum subsequence sum in a given array // There's a triply nested loop over the array so it's O(n^3) public static int maxSum1(int[] a) { int max = 0; for (int i = 0; i < a.length; i++) { for (int j = i; j < a.length; j++) { int sum = 0; // elements from a[i] to a[j] for (int k = i; k <= j; k++) { sum += a[k]; } if (sum > max) { max = sum; } } } return max; } // Calculates and returns the maximum subsequence sum in a given array // There's a doubly nested loop over the array so it's O(n^2) // pre: a.length > 0 public static int maxSum2(int[] a) { int max = a[0]; for (int i = 0; i < a.length; i++) { int sum = 0; for (int j = i; j < a.length; j++) { sum += a[j]; // int sum = 0; // elements from a[i] to a[j] // for (int k = i; k <= j; k++) { // sum += a[k]; // } if (sum > max) { max = sum; } } } return max; } // Calculates and returns the maximum subsequence sum in a given array // Keeps a running sum, resetting the sum to 0 if values go negative. O(n) // pre: a.length > 0, a has some positive values public static int maxSum3(int[] a) { int max = a[0]; int sum = 0; for (int i = 0; i < a.length; i++) { // Claim 2: if sum becomes negative, max range cannot start // with any previous values if (sum < 0) { sum = 0; } sum += a[i]; if (sum > max) { max = sum; } } return max; } // Uses specified algorithm to compute max subsequence sum on randomly // generated array of given size. Prints time elapsed. // pre: size > 0 and 1 <= algorithm <= 3 public static double timingTest(int algorithm, int size) { int[] values = new int[size]; Random rand = new Random(); for (int i = 0; i < values.length; i++) { values[i] = rand.nextInt(1001) - 500; // positive and negative } // get start/stop system times to find out how fast the code ran long startTime = System.currentTimeMillis(); int sum = findMax(algorithm, values); double elapsed = (System.currentTimeMillis() - startTime) / 1000.0; // report and return results System.out.println("\tfor n = " + size + ", time = " + elapsed); return elapsed; } // Finds the maximum subsequence sum using the specified algorithm. // pre: 1 <= algorithm <= 3, throws IllegalArgumentException otherwise. public static int findMax(int algorithm, int[] values) { if (algorithm == 1) { return maxSum1(values); } else if (algorithm == 2) { return maxSum2(values); } else if (algorithm == 3) { return maxSum3(values); } else { throw new IllegalArgumentException( "Algorithm number must be between 1 and 3"); } } }