最大子序列的和问题

来源:互联网 发布:最新版itunes软件下载 编辑:程序博客网 时间:2024/06/11 00:32

问题描述:给出一个整数数组:a1, a2, a3, … … an;求最大的子序列和(如果数组都为负数,则为0)

方法1:遍历求解
从数组的首元素a1开始遍历,一直累加ak,求出最大值。

maxsum: 要求的最大子序列和,
tempsum: a[i]+a[i+1]+a[i+2]+…+a[n-1];(0<=1

//O(N^2)int maxfun(int a[], int n){    int maxsum = 0;    for (int i = 0; i < n; i++)    {        int  tempsum = 0;        for(int j = i; j < n; j++)        {            tempsum += a[j];            if(tempsum > maxsum) maxsum=tempsum;        }    }    return maxsum;}

方法二:考虑到这样一种情况:在遍历求解时,如果子序列开始的元素a[k]为负数,则该子序列不可能为最大子序列和,因为从a[k+1](如果a[k+1]>0)的子序列的和肯定会比它大。这样就可以跳过与负数开头的遍历求解。

int maxfun2(int a[], int n){    int maxsum = 0;    for (int i = 0; i < n; i++)    {        int tempsum = 0;        if(a[i] < 0) continue;        for (int j = i; j < n; j++)        {            tempsum += a[j];            if(tempsum > maxsum) maxsum = tempsum;        }    }    return maxsum;}

后来查看相关资料,发现上诉代码可以进行优化:

//O(N)int maxfun3(int a[], int n){    int maxsum = 0, tempsum = 0;    for (int i = 0; i < n; i++)    {        tempsum += a[i];        if(tempsum > maxsum) maxsum = tempsum;        if(tempsum < 0) tempsum = 0;//如果当前序列开始为负数,或者累加和已为负值,将其置于0    }    return maxsum;}

还有一种分治的方法求解该题。最大子序列可能在三个地方出现,或者在左半部,或者在右半部,或者跨越输入数据的中部而占据左右两部分。前两种情况递归求解,第三种情况的最大和可以通过求出前半部分最大和(包含前半部分最后一个元素)以及后半部分最大和(包含后半部分的第一个元素)相加而得到。

这里写图片描述

//O(NlogN)int max3(int a, int b, int c){    if(a < b)        a = b;    if(a > c)        return a;    else         return c;}int maxfun4(int a[], int left, int right){    int maxleftsum = 0, maxrightsum = 0, maxleftbordersum = 0, maxrightbordersum = 0, leftbordersum = 0, rightbordersum = 0, center, i;    if(left == right)    {        if(a[left] > 0) return a[left];        else return 0;    }    center = (left + right) / 2;    maxleftsum = maxfun4(a, left, center);    maxrightsum = maxfun4(a, center + 1, right);    for (i = center; i >= left; i--)    {        leftbordersum += a[i];        if(leftbordersum > maxleftbordersum)            maxleftbordersum = leftbordersum;    }    for (i = center + 1; i <= right; i++)    {        rightbordersum += a[i];        if(rightbordersum > maxrightbordersum)            maxrightbordersum = rightbordersum;    }    return max3(maxleftsum, maxrightsum, maxleftbordersum + maxrightbordersum);}

reference:http://www.cnblogs.com/CCBB/archive/2009/04/25/1443455.html

0 0
原创粉丝点击