最大子序列和问题

问题描述:给定一个整数序列(可能有负数),求一子序列(记为L‘)使得该子序列所有元素之和最大。例:给定序列-2,11,-4,13,-5,-2,则最大子序列和为20(11,-4,13)


方法一:遍历穷举——O(n^2)


方法二:分治递归——O(n*logn)

思路:将输入序列L分为左右两个子序列L1和L2,则L’只可能以下面三种情况出现:

  • L‘完全在L1中,则L’也是L1中具有最大子序列和的子序列
  • L‘完全在L2中,则L’也是L2中具有最大子序列和的子序列
  • L‘跨越L1和L2,则分别求出L1中包含最后一个元素的所有序列中的和最大的那个(记为L1’)以及L2中包含第一个元素的所有序列中的和最大的那个(记为L2‘),则L’=L1‘+L2’
因此,前两种情况实际上是一种递归,对于情况三,可以采用遍历。最后,求出三种情况中最大的那个,即是所求最终结果

方法三:动态规划——O(n)
思路:不断计算子序列的和,若大于当前最大子序列和,则更新;若当前子序列和小于0,只会为后续序列增加负担,因此全部丢弃,继续扫描(思考一下,L‘中包含最左边元素的任意子序列的和都不可能小于0,否则L’就不可能是L中具有最大和的子序列)

想想,若子序列(A[s], ..., A[t])之和小于0,为什么全部丢弃而不考虑(A[s+1], ..., A[t])或者(A[s+2], ... A[t])呢?因为既然走到这一步,说明(A[s], ..., A[t])左边任意部分如(A[s])或者(A[s], A[s+1])它们各自的和不可能小于0,否则早就被丢弃了。因此,(A[s+1], ..., A[t])或者(A[s+2], ... A[t])只可能比(A[s], ..., A[t])更小。也就是说,若(A[s], ..., A[t])小于0,则(A[s+1], ..., A[t])或者(A[s+2], ... A[t])必然小于0,带上它们只会给后续序列增加负担

利用动态规划算法的代码如下:
int max_subseq_sum(int a[], int n){
	int this_sum = 0, max_sum = 0;
	for(int i = 0; i < n; i++){
		this_sum += a[i];
		if(this_sum > max_sum)
			max_sum = this_sum;
		else if(this_sum < 0)  //丢弃很关键
			this_sum = 0;
	}
	return max_sum;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值