求最大子序列和之线性时间

算法导论里详细说了用时O(nlgn)的算法,主要思路是:

这个序列必定在——左半部分,右半部分,跨越中间的元素的一段序列。

使用的是分治思想,不过左右段搜索可是用了n的时间啊。

这里课后题阐述要给出一个O(n)的算法,显然,对于这个提示:

你只能扫描!

而且也就几次扫描!

否则就不是n的时间了。

我们这么来考虑:

一个数组序列的数字有正有负,最大子序列的最小值至少是0(全是负值,但我们选择了0个元素的子序列),

所以我们有一个初始“最大序列和”:max_sum=0,

显而易见的是我们要一个临时求和变量temp_sum来记录,一旦大于max_sum了,那就赋值给max_sum;

重头戏来了:对于一个刚好求和完毕使得temp_sum小于0的迭代来说,我们要给temp值赋值为0!

可以这样想:

如果刚好让其大于等于0,那等等看,万一后边那个让temp变得更大了呢?

但是如果小于0就算了, 就算加了后面元素,这个temp值也是拖累(减小子序列和大小)

所以直接重新从后面部分开始估计。

不过没关系,已经不要的这一段序列最大和已经被max值保存了。

因此这个函数极为简洁:

def find_max_subarray(arr):
    max_sum,temp_sum=0,0
    for x in arr:
        temp_sum+=x
        if temp_sum>max_sum:
            max_sum=temp_sum
        if temp_sum<0:
            temp_sum=0
    return max_sum

很显然,一遍遍历,仅需要n次迭代。估计是最快的方法了。

这个应用很广,比如给了每天产品价格要求出哪天买入、卖出收益最大。

那就要初始化一个序列来记录变化量,比如[3,5,2,7]

那么变化量就是[2,-3,5](后面元素减去前面的)

然后我们要求出最大子序列和(的范围)便是最大的收益。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值