題目:給定n個整數(可能為負整數)組成的序列a1,a2,a3,a4,a5,..an,求該序列子段和的最大值,「子段和」定義為連續(下標遞增)的元素之和。當所有的整數均為負整數時定義其最大子段和為0。如序列為時,最大子段和為20。
該問題可以用分治法或者動態規劃來求解。下面給出兩種演算法的思路及**實現
思路:將所給的序列分為長度相等的兩部分[1,n/2]和[n/2+1,n],分別求出這兩部分的最大子段和,整個序列的最大欄位和有三種情形:
(1)[1,n]的最大子段和與[1,n/2]的最大子段和相同
(2)[1,n]的最大子段和與[n/2+1,n]的最大子段和相同
(3)[1,n]的最大子段和為a(i)+a(i+1)+a(i+2)+...+a(j),且1 <= i <= n/2,n/2+1 <= j <= n。
對於(1)(2)可遞迴求得,對於情形(3),可看出a[n/2]與a[n/2+1]在最優子串行中。因此,可以在[1,n/2]中計算出s1(範圍是i~n/2之間),並在[n/2+1,n]中計算出s2(範圍在n/2+1~j之間),則s1+s2即為出現情形三(3)時的最優解。
**實現:
//最大子段和
int maxsubsum(int arr,int left,int right)
} int s2=0;
int rights=0;
for(int i=mid+1;i<=right;++i)
}sum=s1+s2;
if(sum執行結果如圖:
該演算法的計算時間t(n)滿足典型的分治演算法遞迴式:
解此遞迴方程可知,t(n)=o(nlogn)。
思路:遍歷序列,定義變數b[j](注意這並不是陣列,而是乙個int型變數)為截止到當前遍歷點的最優解,由其定義可知,當b[j-1]>0時,b[j]=b[j-1]+a[j],否則b[j]=a[j]。由此可得計算b[j]的動態規劃遞迴式為:
b[j]=max, 1 <= j <= n
**實現:int maxsum(int arr,int n)
if(b>sum) sum=b;
} return sum;
}int main()
; int n=sizeof(arr)/sizeof(arr[0]);
int res=maxsum(arr,n);
cout執行結果截圖:
顯然,該動態規劃需要o(n)計算時間和o(n)空間。
通過上述分析,求解該問題時,無論是從演算法的時間複雜度還是**編寫的難易程度來看,動態規劃演算法要更勝一籌。
最大子段和問題(分治法和動態規劃)
什麼是最大子段和,通俗點講 最大子段和就是給了一些數,然後你從中找了幾個連續的數,這組連續的數的和比任意一組連續的數的和都大,那麼你找的這幾個連續的數的和就是這些數的最大子段和。通俗的聽不懂你就看這裡 給定由n個整數 可能為負整數 組成的序列 分治法思想 如果將所給的序列a 1 n 分為長度相等的兩...
最大子段和 分治與動態規劃
問題 給定n個整數 可能為負數 組成的序列a 1 a 2 a 3 a n 求該序列如a i a i 1 a j 的子段和的最大值。當所給的整均為負數時定義子段和為0,依此定義,所求的最優值為 max,1 i j n 例如,當 a1,a2,a3,a4,a4,a6 2,11,4,13,5,2 時,最大子...
最大子段和 分治與動態規劃
問題 給定n個整數 可能為負數 組成的序列a 1 a 2 a 3 a n 求該序列如a i a i 1 a j 的子段和的最大值。當所給的整均為負數時定義子段和為0,依此定義,所求的最優值為 max,1 i j n 例如,當 a1,a2,a3,a4,a4,a6 2,11,4,13,5,2 時,最大子...