public class Test { // 最大連續子序列積 // 假設有集合A,Max[n]表示從A[0]~A[n]的以A[n]結尾的最大連續子序列積, // Min[n]表示從A[0]~A[n]的以A[n]結尾的最小子序列積,則有如下遞推式 // Max[n] = Max{ Max[n-1]*A[n], A[n], Min[n-1]*A[n] } // Min[n] = Min{ Max[n-1]*A[n], A[n], Min[n-1]*A[n] } private static void getMaxProduct(float[] a) { float[] maxArr = new float[a.length]; float[] minArr = new float[a.length]; maxArr[0] = a[0]; minArr[0] = a[0]; float maxProduct = a[0]; int maxStartInx = 0; //最大連續序列積開始座標 int maxEndInx = 0; //最大連續序列積結束座標 int curMaxStartInx = 0; //當前最大積開始座標 int preMaxStartInx = 0; //上一個最大積開始座標 int curMinStartInx = 0; //當前最小積開始座標 int preMinStartInx = 0; //上一個最小積開始座標 for (int i = 1; i < a.length; i++) { maxArr[i] = Math.max(a[i], Math.max(maxArr[i - 1] * a[i], minArr[i - 1] * a[i])); minArr[i] = Math.min(a[i], Math.min(maxArr[i - 1] * a[i], minArr[i - 1] * a[i])); if (maxProduct < maxArr[i]) { maxProduct = maxArr[i]; //序列座標更新 if (maxArr[i] == a[i]) { maxStartInx = maxEndInx = i; } else if (maxArr[i] == maxArr[i - 1] * a[i]){
maxStartInx = preMaxStartInx;
maxEndInx = i; } else { // 如果maxArr[i]是通過minArr[i-1]*a[i]得到, // 說明其序列開始座標等於上一個元素的最小連續序列積的開始座標 maxStartInx = preMinStartInx; maxEndInx = i; } } //記錄當前最小連續子序列積的開始座標 if (minArr[i] == a[i]) { curMinStartInx = i; } else if (minArr[i] == maxArr[i - 1] * a[i]) { curMinStartInx = preMaxStartInx; } //記錄當前最大連續子序列積的開始座標 if (maxArr[i] == a[i]) { curMaxStartInx = i; } else if (maxArr[i] == minArr[i - 1] * a[i]){ curMaxStartInx = preMinStartInx; } preMaxStartInx = curMaxStartInx; preMinStartInx = curMinStartInx; } System.out.println("MaxProduct: " + maxProduct + " Start: " + maxStartInx + " End: " + maxEndInx); } public static void main(String[] args) { float[] a = {1.4f, 8, 0.9f, -2, 0.7f, -4, 0, 3, 9, -1, 0.55f, 100, -2}; getMaxProduct(a); }}