最大子序列和(连续):

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

 

 

 

posted @ 2015-05-25 14:13  M_Kepler  阅读(262)  评论(0编辑  收藏  举报