最大子段问题

算法描述如下

如果将所给的序列a[1:n]分为长度相等的两段a[1:n/2]和a[n/2+1:n],分别求出这两段的最大子段和,则a[1:n]的最大子段和有三种情况:
(1) a[1:n]的最大子段和与a[1:n/2]的最大子段和相同
(2) a[1:n]的最大子段和与a[n/2+1:n]的最大子段和相同
(3) a[1:n]的最大子段和为a[i]+…+a[j],并且1<=i<=n/2,n/2+1<=j<=n。
对于(1)和(2)两种情况可递归求得,但是对于情况(3),容易看出a[n/2],a[n/2+1]在最大子段中。因此,我们可以在a[1:n/2]中计算出s1=max(a[n/2]+a[n/2-1]+…+a[i]),0<=i<=n/2,并在a[n/2+1:n]中计算出s2= max(a[n/2+1]+a[n/2+2]+…+a[i]),n/2+1<=i<=n。则s1+s2为出现情况(3)的最大子段和。据此可以设计出最大子段和问题的分治算法如下:
时间复杂度:O(NlogN)
#include<stdio.h>

int maxsum(int a[], int left, int right)
 {
 if (left == right) return a[left];
 else
 {
 int mid = (right + left) / 2;
 int leftsum = maxsum(a, left, mid);
 int rightsum = maxsum(a, mid + 1, right);
 int rights = 0, s1 = 0, lefts = 0, s2 = 0;
 for (int i = mid + 1; i <= right; i++)//右边
 {
 rights += a[i];
 if (rights > s1) s1 = rights;
 }
 for (int i = mid; i >= left; i--)//左边
 {
 lefts += a[i];
 if (lefts > s2) s2 = lefts;
 }
 if ((s1 + s2) < leftsum) return leftsum;
 if ((s1 + s2) < rightsum) return rightsum;
 }

}
 int main()
 {
 int a[] = { -5,11,-4,13,-4,-2 };
 printf("%d\n", maxsum(a, 0, 5));
 return 0;
 }
输出:
20
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值