最大子序和-线性算法,最顶的解释(maxSubsequenceSum)

问题描述

给一段数组,找出一段连续子数组使得元素和最大。
比如16个元素的数组A[13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7]
最大子数组A[7…10],sum=43

上代码

int maxSubsequenceSum(int *a, int num){
	int left=0, right=0, sum=0, maxsum=0;
	for(int i = 0; i < num; i++){
		sum += a[i];
		if(sum > maxsum){
			maxsum = sum;
		}
		else if(sum < 0){
			sum = 0;
		}
	}

代码很简单,思路是从左到右遍历元素且累加元素的值,中途记录最大的sum,当sum<0就置sum=0。
最大的疑惑点是为什么sum<0就可以置其为0,这是这段简洁的代码里面最神奇的部分,稍后需要证明,给大伙儿整明白。
《蒜捣》4.1-5原话

使用如下思想为最大子数组问题设计一个非递归的、线性时间的算法。从数组的左边界开始,从左至右处理,记录到目前为止已经处理过的最大子数组。若已知A[1…j]的最大子数组,基于如下性质将解扩展为A[1…j+1]的最大子数组:A[1…j+1]的最大子数组要么是A[1…j]的最大子数组,要么是某个子数组A[i…j+1] (1≤i≤j+1)。在已知A[1…j]的最大子数组的情况下,可以在线性时间内找出形如A[i…j+1]的最大子数组。

如果A[j+1]还有可能包含于之前的MSS(maxSubsequenceSum),那么sum+=A[j+1]。否则从A[j+1]开始重新计算sum。
问题是如何知道A[j+1]会不会包含于之前的MSS。
这里给出一个命题:
“当sum<0时,MSS不再从之前遍历过的元素开始,即A[j+1]不包含于A[i…j+1]”
证明:
假设A[j+1]包含于A[i…j+1]的MSS中,
sum<0,则maxSum<0,与maxSum>=0矛盾,
故A[j+1]必不包含于A[i…j+1]的MSS中。
于是sum<0时寻找MSS的旅程可以与之前的元素告别,重新以A[j+1]为起点开始。

强化版-给出最大连续数组的索引

int maxSubsequenceSum(int *a, int num, int *return_left, int* return_right){
	int left=0, right=0, nowl=0, nowr=0, sum=0, maxsum=0;
	for(int i = 0; i < num; i++){
		sum += a[i];
		if(sum > maxsum){
			maxsum = sum;
			left = nowl;
			right = i;
		}
		else if(sum < 0){
			sum = 0;
			nowl = i + 1;
		}
	}

动动你的小手模拟一下计算可以想明白,sum置0的时候left会置值,更新maxSum时right会置值。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值