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