利用递归求最大子序列

       对于一个序列A1,A2,…….An,求其最大子序列.利用普通的循环来做的话,所花费的时间有点大,便考虑用递归,但递归的缺点也很明显,用空间换时间.但本题也是用于学习递归的比较好的一个例子

e.g.

前半部分后半部分
4 -3 5 -2-1 2 6 -2

       我们对这个序列进行切分,最长序列出现的位置有三个,前半部分,后半部分或者横跨两部分.        横跨前后两部分的话,这个序列至少得包含前一个序列的最后一个元素与后半部分的第一个元素.
       前半部分的最大值是 6, 后半部分最大值为 8, 横跨两部分的话,最大值为11.所以我们可以得出最大自序列产生于A1~A7
       但仔细观察一下,既然一个完整的序列要切成前后两部分,那对于前后两部分,我们还可以再进一步的划分

前半部分后半部分
4 -35 -2-1 26 -2

       同理,不断的划分下去,最后可以划分为单个单个的元素.
       对于这些元素,他们便是最大值,我们只需要比较这两个元素(a[left] and a[right])以及他们的和(a[left]+a[right]),找出一个最大值(max),该最大值又是下一次对比的a[left]或者a[right]元素.

       对于这些划分与取值,当取到最后一个时,即left==right时,便可以返回该元素,使其等于 maxleftsum 或 rightmaxsum.书上的代码对小于0的情况一律返回0,个人觉得不大喜欢,便修改一下,使其直接返回该元素.这样即使全是负数,也可以求得最大值.

       当递归到单个元素返回之后,便可以对横跨前后部分的序列进行求值.利用两个for循环,分别从center向left和right方向进行循环,记录其中最大值maxleftbordersummaxrightbordersum之后记录他们的和便是横跨前后部分的最大值.
以下为代码部分:

int maxsubsum (int a[], int left, int right)
{
int maxleftsum, maxrightsum;
int maxleftbordersum, maxrightbordersum;
int leftbordersum, rightbordersum;
int center, i;

if (left == right)
    return a[left];

center = (left+right) / 2;
maxleftsum = maxsubsum(a, left, center);
maxrightsum = maxsubsum(a, center+1, right);

leftbordersum = 0;
maxleftbordersum = a[center];
for (i = center; i >= left; i--)
{
    leftbordersum += a[i];
    if (leftbordersum > maxleftbordersum)
        maxleftbordersum = leftbordersum;
}

rightbordersum = 0;
maxrightbordersum = a[center+1];
for (i = center+1; i <= right; i++)
{
    rightbordersum += a[i];
    if (rightbordersum > maxrightbordersum)
    maxrightbordersum = rightbordersum;
}

return max3 (maxleftsum, maxrightsum, maxleftbordersum+maxrightbordersum);
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值