一、比較朴素的算法
算法思想:我們確定每個子段和開始的位置,分別為第一個,第二個,第三個......第N個,然后計算從這個位置開始到這個位置之后的每個位置的子段和,更新記錄最大的子段和。
時間復雜度:O(n^2)
算法實現(Java):
package com.Third; import java.util.*; public class Main3{ public static int maxSum2(int a[]){ int nowSum=0;//用於記錄從指定位置到當前位置累加的值 int maxSum=0;//用於記錄當前最大的子段和 for(int i=0;i<a.length;i++){ nowSum=0; for(int j=i;j<a.length;j++){ nowSum=nowSum+a[j]; if(nowSum>maxSum){//更新最大子段和 maxSum=nowSum; } } } return maxSum; } public static void main(String[] args) { int a[]={4,-3,5,-2,-1,2,6,-2}; System.out.println(maxSum2(a)); } }
二、分治法(遞歸)
算法思想:
通過分治的思想求最大子段和,將數組分平均分為兩個部分,則最大子段和會存在於三種情況下:
1.最大子段和出現在左端
2.最大子段和出現在右端
3.最大子段和橫跨在左右段 通過比較大小得到最大子段和
時間復雜度:O(nlogn)
算法實現(Java):
package com.Third; /* * 通過分治的思想求最大子段和,將數組分平均分為兩個部分,則最大子段和會存在於三種情況下: * 1.最大子段和出現在左端 * 2.最大子段和出現在右端 * 3.最大子段和橫跨在左右段 */ public class Main { public static int maxSumRec(int []a,int start,int end){ if(start==end){//這里是遞歸的函數出口 if(a[start]>0){ return a[start]; }else{ return 0; } } int maxLeftSumRec=maxSumRec(a,start,(start+end)/2);//計算左半邊的最大字段和 int maxRightSumRec=maxSumRec(a,((start+end)/2)+1,end);//計算右半邊最大子段和 //計算最大子段和在中間的情況 int leftMaxMark=0; int leftSum=0; for(int i=(start+end)/2;i>=0;i--){ leftSum=leftSum+a[i]; if(leftSum>leftMaxMark){ leftMaxMark=leftSum; } } int rightMaxMark=0; int rightSum=0; for(int i=((start+end)/2)+1;i<=end;i++){ rightSum=rightSum+a[i]; if(rightSum>rightMaxMark){ rightMaxMark=rightSum; } } int maxMidSumRec=leftMaxMark+rightMaxMark; //比較三種情況那種情況是最大的子段和 int maxSum=maxLeftSumRec; if(maxSum<maxRightSumRec){ maxSum=maxRightSumRec; } if(maxMidSumRec>maxSum){ maxSum=maxMidSumRec; } return maxSum; } public static void main(String[] args) { int a[]={4,-3,5,-2,-1,2,6,-2}; System.out.println(maxSumRec(a,0,7)); } }
三、動態規划算法
算法思想:
運用了動態規划的思想來解決最大子段和問題:
通過遍歷累加這個數組元素,定時的更新最大子段和,
如果當前累加數為負數,直接舍棄,重置為0,然后接着遍歷累加。
時間復雜度:O(n)
算法實現(Java):
package com.Third; /* * 這是運用了動態規划的思想來解決最大子段和問題: * 通過遍歷累加這個數組元素,定時的更新最大子段和, * 如果當前累加數為負數,直接舍棄,重置為0,然后接着遍歷累加。 */ public class Main1{ public static int maxSubSum1(int []a){ int maxSum=0; int nowSum=0; for(int i=0;i<a.length;i++){ nowSum=nowSum+a[i]; if(nowSum>maxSum){//更新最大子段和 maxSum=nowSum; } if(nowSum<0){//當當前累加和為負數時舍棄,重置為0 nowSum=0; } } return maxSum; } public static void main(String[] args) { int a[]={4,-3,5,-2,-1,2,6,-2}; System.out.println(maxSubSum1(a)); } }