如何计算一个整形数组里的连续元素和的最大值?

转自 http://www.yl1001.com/ask/41004/question/5461393293384111.htm

例:{9, -12, 120, 8, -20, 100, 30, -89, 20} 结果是{120, 8 , -20, 100, 30}的和最大,为 238 函数声明: int max_sum(int *array, int array_len);请计算一个整形数组里的连续元素和的最大值,求方法~将问题转变转变,其实也可以考虑一下,如何求一个整形数组里的非连续元素和的最大值~


这是一个比较典型的说明算法效率差异的题目。最笨也是最简单的算法的效率是O(N*N),如果注意到结果的可重复利用,可以实现O(N*LogN)的算法,但是最优的计算复杂度是O(N)。无论如何至少要遍历一遍整个数组,所以不可能有O(1)的实现方法。上面大家给出了很多的算法,liukun提出的分治的方法,这个问题不应该是分治问题,用分治的方法只会把问题搞复杂,它的计算复杂度应该是O(N*LogN)。唐仕强和黄文彬给出的都是O(N)的解决方案,没有太仔细看,但我想结果都应该是对的,有问题也是对一些特殊情况的处理上,譬如对全部是负数的特殊情况的考虑,但是这些不影响整个算法的解体思路。问题的关键是如何自然地写出O(N)的算法。下面给出一个思考该算法的思路。

首先将问题描述形式化如下:
1 记数组为 A,其元素从0到n-1。
2 数组A的子数组记为A[i,j],表示[i,j]闭区间区域的子数组。
3 子数组A[i,j]的和记为SA[i,j]
4 问题目标是寻找S[i,j]的最大值,记为MaxS[0,n-1]
分析问题内在的性质,引入一个中间函数,
X[i]表示所有以i为右边界的子数组的集合,即{A[0,i],A[1,i]...A[i, i]}
MaxX[i]= max(SA[j,i]),其中 j=[0, i],表示X[i]集合中最大的子数组的和。
MaxX[i]记录的是以i为右端点的最大子数组和。它显然符合以下递推公示,
MaxX[i]= Max[i-1]+A[i](Max[i-1]>= 0)
= A[i] (Max[i-1]< 0)
所以MaxX[i]可以很容易计算,而最终的目标结果就是MaxX[i]的最大值
MaxS[0, n-1] = max(MaxX[i]),其中i=[0, n-1];

根据以上的分析,算法的代码实现就会比较自然流畅,java实现如下:

int sum = A[0];
int left = 0;
int leftOfMax = 0;
int rightOfMax = 0;
int maxSum = A[0];
for(int i = 1; i<A.length; i++){
   if(sum < 0){
       sum = A[i];
       left = i;
   }else{
       sum = sum + A[i];
   }

   if(sum > maxSum){
       maxSum = sum;
       leftOfMax = left;
       rightOfMax = i;
   }
}

//这里maxSum为目标结果,其所对应的子数组为A[leftOfMax, rightOfMax].

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值