最大子序列和的线性时间解法

问题描述:给定整数A1,A2,...An(可能有负数)。求 的最大值。(如果所有的整数都是负数,则最大子序列和为0。)

程序代码

int maxSubSum(const vector<int>&a)
{
	int maxSum = 0;
	int thisSum = 0;
	for(int i = 0;i < a.size();i++)
	{
		thisSum += a[i];//新读取一个数
		if(thisSum > maxSum)//这次的结果比最大序列还大
		{
			maxSum = thisSum;
		}
		if(thisSum < 0)//推进i
		{
			thisSum = 0;
		}
	}
	return maxSum;
}

解释:

1.最大子序列的第一个元素不会是负的。即,如果a[i]是负的,那么它不可能是最大子序列的起点。因为任何用a[i]开头的序列,此时都不如用a[i+1]开头的序列和大。


2.同理,任何负的子序列都不可能是最优子序列的前缀。即,如果我们在内循环中检测到a[i]到a[j]的和是负的,那么我们可以推进i,关键的结论是我们不光可以推进到i+1,实际上我们可以直接推进到j+1。说明:令p是i+1到j之间的任何一个下标,因为j下标是第一个使从a[i]开始的序列变负的下标,所以,从a[i]到a[p]的序列和为正数。也就是说任何从p开始的子序列,都不如这个序列再加上a[i]到a[p-1]这个序列的和大。所以我们可以直接推进到j+1。

通过这个例子我们可以发现,许多聪明的算法,运行时间是明显的,本例是O(N),但是正确性不是那么明显。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值