//最大子序列和(連續): //http://my.oschina.net/itblog/blog/267860 #include <iostream> using namespace std; int MaxSum(int* a, int n) { int sum = 0; int max = 0; //最大子序列第一個元素不可能是負數, //不可能包含和為0或負數的子序列作為前綴 //這樣的話就避免了對同一個元素進行多次考慮 for(int i=0; i<n; i++) { sum += a[i]; if(sum > max ) max = sum; else if(sum<0) sum=0; } return sum; } int main() { int a[]={-1,-2,-3,-4}; //測試全是負數的用例 cout<<MaxSum(a,4)<<endl; int b[10]={1, -2, 3, 10, -4, 7, 2, -5}; cout<<MaxSum(b,8)<<endl; system("pause"); return 0; } /* 比如數組:1, -2, 3, 10, -4, 7, 2, -5 最大子序列和為13 一種是暴力枚舉O(n^3),兩個for循環確定邊界,第三個for循環遍歷相加比較。 for(i=0,i---n) for(j=i,j---n) for(k=i,k---n) sum+=s[k] 一種遍歷O(n^2):第二個for循環裡j一邊移動一邊相加然後比較。 for(i=0,i---n) for(j=i,j---n) sum+=s[j] 一種是用DP來考慮,最大子序列要麼是在左半,要麼是在右半,要麼 橫跨左右O(nlogn)。 一種是線性的,如上O(n) */
//分治法:/要看看遞歸和二分了 #include <iostream> using namespace std; //求三個數最大值 int max3(int i, int j, int k) { if (i>=j && i>=k) return i; return max3(j, k, i); } int maxsequence2(int a[], int l, int u) { if (l > u) return 0; if (l == u) return a[l]; int m = (l + u) / 2; //求橫跨左右的最大連續子序列左半部分 int lmax=a[m], lsum=0; //這個循環是求這個序列的最大值,把所有元素相加 for (int i=m; i>=l; i--) { lsum += a[i]; if (lsum > lmax) lmax = lsum; } //求橫跨左右的最大連續子序列右半部分 int rmax=a[m+1], rsum = 0; for (int i=m+1; i<=u; i++) { rsum += a[i]; if (rsum > rmax) rmax = rsum; } //如果最大子序列跨越左半邊和右半邊的話,那麼就是左半邊的lmax和右半邊的rmax的和。 return max3(lmax+rmax, maxsequence2(a, l, m), maxsequence2(a, m+1, u)); } int main() { //int a[]={-1,-2,-3,-4}; //測試全是負數的用例 //cout<<MaxSum(a,4)<<endl; int a[10]={1, -2, 3, 10, -4, 7, 2, -5}; cout<<maxsequence2(a, 0,8)<<endl; system("pause"); return 0; }