1 package com.demo.acm; 2 3 import java.util.*; 4 5 public class Main2 { 6 7 /** 8 * 求解一个数组相邻数相乘的最大值 例如 1 2 3 0 3 7 :21 方法一:时间复杂度为O(n*n),统计每一个子序列乘积 9 */ 10 private static double computeMultip1(double[] numb) { 11 double result = numb[0]; 12 double tmpresult = 1; 13 for (int i = 0; i < numb.length; i++) { 14 for (int j = i; j < numb.length; j++) { 15 tmpresult *= numb[j]; 16 if (tmpresult > result) 17 result = tmpresult; 18 } 19 tmpresult = 1; 20 } 21 return result; 22 } 23 24 /** 25 * 方法二: 扫描一边序列,记录最大值,最小值,和当前最大值,最小值,主要是因为负数的出现, 当当前的最大值小于1时,设置为当前的序列值, 26 * 27 * @param numb 28 * @return 29 */ 30 private static double computeMultip2(double[] numb) { 31 double maxMul = numb[0]; 32 double minMul = numb[0]; 33 double minCur = numb[0]; 34 double maxCur = numb[0]; 35 double tmp; 36 for (int i = 1; i < numb.length; i++) { 37 if (maxCur < 1) 38 maxCur = numb[i]; 39 else 40 maxCur *= numb[i]; 41 minCur *= numb[i]; 42 if (maxCur < minCur) { 43 tmp = maxCur; 44 maxCur = minCur; 45 minCur = tmp; 46 } 47 maxMul = maxCur > maxMul ? maxCur : maxMul; 48 minMul = minCur > minMul ? minCur : maxMul; 49 } 50 return maxMul; 51 } 52 53 /** 54 * 方法三:通过动态规划求解,考虑到可能存在负数的情况,我们用Max[i],来表示以a[i] 55 * 结尾的最大连续子序列的乘积,用Min[i]表示以a[i]结尾的最小的连续子序列的乘积值 那么状态转移方程为: Max[i]=max{a[i], 56 * Max[i-1]*a[i], Min[i-1]*a[i]}; Min[i]=min{a[i], Max[i-1]*a[i], 57 * Min[i-1]*a[i]}; 初始状态为Max[1]=Min[1]=a[1]。代码如下: 58 * 59 * @param args 60 */ 61 private static double computeMul3(double[] numb) { 62 double[] maxMul = new double[numb.length]; 63 double[] minMul = new double[numb.length]; 64 maxMul[0] = numb[0]; 65 minMul[0] = numb[0]; 66 double maxValue = numb[0]; 67 for (int i = 1; i < minMul.length; i++) { 68 maxMul[i] = Math.max(Math.max(numb[i], maxMul[i - 1] * numb[i]), 69 minMul[i - 1] * numb[i]); 70 minMul[i] = Math.max(Math.max(numb[i], maxMul[i - 1] * numb[i]), 71 minMul[i - 1] * numb[i]); 72 maxValue = Math.max(maxMul[i], maxValue); 73 } 74 return maxValue; 75 } 76 77 public static void main(String[] args) { 78 Scanner scanner = new Scanner(System.in); 79 int length = 0; 80 System.out.println("请输入测试数据"); 81 while (scanner.hasNext()) { 82 length = scanner.nextInt(); 83 double[] numb = new double[length]; 84 for (int i = 0; i < numb.length; i++) { 85 numb[i] = scanner.nextDouble(); 86 } 87 double result1 = computeMultip1(numb); 88 double result2 = computeMultip2(numb); 89 double result3 = computeMul3(numb); 90 System.out.println("方法的结果:result1=" + result1 + " result2=" 91 + result2 + " result3=" + result3); 92 } 93 } 94 }
一共使用了三种方法用于求解一个序列的子序列乘积的最大值
动态规划的关键是找一个状态转移方程