生活随笔
收集整理的這篇文章主要介紹了
最大连续子段和
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
最近在學習動態規劃,將自己的所思所想所得記錄下來,檢驗自己是否真正懂了。
?
問題描述:
給定一個數組,記錄一串數字,可正可負,現要求出其中最大的連續子段和。
?
用數組A[N]記錄所要求的數組,用數組B[N]來記錄連續子段和的狀態
通過分析,可以知道:
當B[K]>0時,無論B[K]為何值,B[K]=B[K-1]+A[K]
當B[K]<0時,也就是B[K]記錄到一個A[J]是負的,可以把B[K]變成負的,那么B[J]記錄的這一段應該截掉,應為無論后面的A[K]多大,加上個負數總不可能是最大的子段和,因此將B[K]=A[K],重新開始記錄。
?
故動態轉移方程便可得出
B[K] = MAX(B[K-1]+A[K] , A[K])
?
看個實例
k????? 1????? ?2????? ?3??????? 4
a[k] ?3?????-4???????2????????10
b[k]? 3?????-1?????? 2??????? 12
?
必須記住B[K]是狀態量,要獲得最大連續子段和,只需在數組B中掃描一遍得到最大的數即可。
?一個有N個整數元素的一維數組{A[0],A[1],....,A[N-1],A[N]},這個數組有很多連續的子數組,那么連續子數組之和的最大的一個的值是什么?
? ?先給出一個時間復雜度為O(N^2)的求解程序實現,思想很簡單,就是遍歷數組中所有的子數組,代碼如下:
[java]?view plaincopy
? ? ? ? ?? public?class?MaxSubArraySum?{?? ?????? ????public?static?int?sumN2(int?[]?array){?? ????????int?sum=0,maxSum=Integer.MIN_VALUE;?? ????????int?n=array.length;?? ????????int?count=0;?? ????????for(int?i=0;i<n;i++){?? ????????????sum=0;?? ????????????for(int?j=i;j<n;j++){?? ????????????????sum+=array[j];?? ????????????????if(sum>maxSum){?? ????????????????????maxSum=sum;?? ????????????????}?? ????????????????count++;?? ????????????}?? ????????}?? ????????System.out.println("length="+n+"||count="+count);?? ????????return?maxSum;?? ????}?? ????public?static?void?main(String?[]?args){?? ?? ????????int?[]?array={-5,-2,-3,-5,-3,-2};?? ????????int?sum=MaxSubArraySum.sumN2(array);?? ????????System.out.println("最大子序列和="+sum);?? ????}?? ?? }??
因為子數組求和滿足動態規劃的后無效特性,所以可以使用動態規劃的思想,從分治的算法中得到提示:可以考慮數組的第一個元素A[0],以及最大的一段數組(A[i],...A[j])跟A[0]之間的關系,有一下幾種情況:
1.當0=i=j時,元素A[0]元素本身構成和最大的一段;
2.當0=i<j時,和最大的一段以A[0]開始;
3.當0<i時,元素A[0]跟和最大的一段沒有關系。
從上面的三種情況可以將一個大問題(N個元素的數組)轉化為一個較小的問題(n-1個元素的數組)。假設知道(A[1],...,A[N-1])中包含A[1]的和最大的一段的和為start[1]。那么,根據上面分析的三種情況,不難看出(A[0],...,A[N-1])中問題的解all[0]是三種情況的最大值max{A[0],A[0]+start[1],all[1]}。通過問題分析,可以看到問題滿足無后效性,可以使用動態規劃的方法來解決。
程序代碼實現如下:
[java]?view plaincopy
? ? ? ? ?? public?static?int?sumN(int?[]?array){?? ????int?n=array.length;?? ????int?all=array[n-1],start=array[n-1];?? ????int?count=0;?? ????for(int?i=n-2;i>=0;i--){?? ????????if((start+array[i])>array[i]){?? ????????????start=start+array[i];?? ????????}else{?? ????????????start=array[i];?? ????????}?? ????????if(all<start){?? ????????????all=start;?? ????????}?? ????????count++;?? ????}?? ????System.out.println("數組長度="+array.length+"||時間復雜度="+count);???? ????return?all; ?
總結
以上是生活随笔為你收集整理的最大连续子段和的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。