最大子序列求和_绝妙的算法——最大子序列和问题

问题的引入

给定(可能有负数)整数序列A1, A2, A3..., An, 求这个序列中子序列和的最大值。(为方便起见,如果所有整数均为负数,则最大子序列和为0)。例如:输入整数序列: -2, 11, 8, -4, -1, 16, 5, 0,则输出答案为35,即从A2~A6。

这个问题之所以有吸引力,主要是因为存在求解它的很多算法,而这些算法的性能差异又很大。这些算法,对于少量的输入差别都不大,几个算法都能在瞬间完成,这时若花费大量的努力去设计聪明的算法恐怕就不太值得了;但是如果对于大量的输入,想要更快的获取处理结果,那么设计精良的算法显得很有必要。

切入正题

下面先提供一个设计最不耗时间的算法,此算法很容易设计,也很容易理解,但对于大量的输入而言,效率太低:

算法一:

public static int maxSubsequenceSum(int[] a) {

int maxSum = 0;

for(int i=0; i

for(int j=i; j

int thisSum = 0;

for(int k=0; k<=j; k++)        //迭代子序列中的每一个元素,求和

thisSum += a[k];

if(thisSum > maxSum)

maxSum = thisSum;

}

}

return maxSum;

}

上述设计很容易理解,它只是穷举各种可能的结果,最后得出最大的子序列和。毫无疑问,这个算法能够正确的得出和,但是如果还要得出是哪个子序列,那么这个算法还需要添加一些额外的代码。

现在来分析以下这个算法的时间复杂度。运行时间的多少,完全取决于第6、7行,它们由一个含有三重嵌套for循环中的O(1)语句组成:第3行上的循环大小为N,第4行循环大小为N-i,它可能很小,但也可能是N。我们在判断时间复杂度的时候必须取最坏的情况。第6行循环大小为j-i+1,我们也要假设它的大小为N。因此总数为O(1*N*N*N)=O(N3)。第2行的总开销为O(1),第8、9行的总开销为O(N2),因为它们只是两层循环内部的简单表达式。

我们可以通过拆除一个for循环来避免3次的运行时间。不过这不总是可能的,在这种情况下,算法中出现大量不必要的计算。纠正这种低效率的改进算法可以通过观察Sum(Ai~Aj) = Aj + Sum(Ai~A[j-1])而看出,因此算法1中第6、7行上的计算

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值