最大子序列和(连续):
//最大子序列和(连续): //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; }