求最大子序列之和的四種方法
阿新 • • 發佈:2019-02-15
四種求最大子序列和的方法,效率一個比一個高。
方法二是方法一的改進
方法三是採用分治的思想,編寫遞迴函式
方法四 最為巧妙,程式碼少,效率高,邏輯清晰
對原書中的程式碼做了一小點修改,能處理負數陣列(結果為最小的負數)
附上程式碼
package chapter2; import java.util.Random; public class maxSubSum { /*-------------------------------方法1 --------------------------------*/ public int maxSubSum1(int[] a)//方法1 { //最笨的方法,分別以每個元素為起點 計算每一種長度的和 int sum=a[0],sumMax=a[0]; for (int i = 0; i < a.length; i++)//每一個元素為起點 { for (int j = i; j < a.length; j++)//每一種子序列長度 { sum=a[i]; for(int k=i+1;k<=j;k++)//求和 sum+=a[k]; if (sumMax<sum)//比較更新Max { sumMax=sum; } } } return sumMax; } /*-------------------------------方法2 --------------------------------*/ public int maxSubSum2(int[] a)//方法二 { //方法一的改進,通過一個for迴圈直接得出 某個元素為起點的所有子序列的最大和 int sum=0,sumMax; sumMax=a[0]; for (int i = 0; i < a.length; i++)//選取每一個元素為起點 { sum=0; for (int j = i; j < a.length; j++)//比較每一種序列的和 { sum+=a[j]; if (sum>sumMax) sumMax=sum; } } return sumMax; } /*-------------------------------方法3 --------------------------------*/ public int maxSubSum3(int[] a,int left,int right)//方法三 { //分治策略 //每次把陣列分成左右兩部分, //最大子序列和可能在三處出現,整個序列出現在左邊或者右邊,或者跨越中部 if (left==right) //基本情況,left=right,只有一個元素 return a[left]; int center=(left+right)/2;//遞迴,繼續分成左右兩部分, int maxLeftSum=maxSubSum3(a, left, center);//返回左邊的最大和 int maxrightSum=maxSubSum3(a, center+1, right);//返回右邊的最大和 //計算從center為起點,分別向左和向右的最大序列和 //center向左的最大子序列和 int maxLeftBorderSum=a[center],leftBorderSum=a[center]; for (int i = center-1; i >= left; i--) { leftBorderSum+=a[i]; if (leftBorderSum>maxLeftBorderSum) maxLeftBorderSum=leftBorderSum; } //center向右的最大子序列和 int maxrightBorderSum=a[center+1],rightBorderSum=a[center+1]; for (int i = center+2; i <=right; i++) { rightBorderSum+=a[i]; if (rightBorderSum>maxrightBorderSum) maxrightBorderSum=rightBorderSum; } //返回三種情況的最大值(整個在左邊,整個在右邊,跨區域) int max; max=maxLeftSum>maxrightSum? maxLeftSum:maxrightSum; max=max>maxLeftBorderSum+maxrightBorderSum?max:maxLeftBorderSum+maxrightBorderSum; return max; } /*-------------------------------方法4 --------------------------------*/ public int maxSubSum4(int[] a)//方法四 { //效率最高,程式碼最簡單 //思路:小於0的子序列(包括單個元素的情況)比較sumMax後直接拋棄,sum重置為0,繼續累加 int sum=a[0],sumMax=a[0]; for (int i = 1; i < a.length; i++) { sum+=a[i]; if (sum>sumMax) sumMax=sum; if (sum<0) sum=0; } return sumMax; } public static void main(String[] args) { int[] a=new int[1000]; for (int i = 0; i < a.length; i++)//隨機數給陣列賦值 { a[i]=(int )( (0.5-Math.random())*100); if (a[i]==0) a[i]=-8; } maxSubSum test=new maxSubSum(); System.out.println(test.maxSubSum4(a)); System.out.println(test.maxSubSum3(a,0,999)); System.out.println(test.maxSubSum2(a)); System.out.println(test.maxSubSum1(a)); } }