寻找最大子列元素和的巧妙算法

寻找最大子列元素和的巧妙算法

根据用户的输入生成一个数列A,要求出:
∑ k = i j A k \sum_{k=i}^jA_k k=ijAk
的最大值。
为了方便表述,我们记满足要求的数列为B,假设B中共有m个元素,并且
B 0 = A i , B m − 1 = A j B_0=A_i, B_{m-1}=A_j B0=Ai,Bm1=Aj
也就是说
A i 是 B 中 的 第 一 个 元 素 , A j 是 B 中 的 最 后 一 个 元 素 A_i是B中的第一个元素,A_j是B中的最后一个元素 AiBAjB

int MaxSubSum(int N)  //N是用户输入数列元素个数-1
{
	int i, TheSum, MaxSum;

	TheSum = MaxSum = 0;

	for (i = 0; i < N; i++)
	{
		TheSum += NumberList[i];    //1

		if (TheSum > MaxSum)
		{
			MaxSum = TheSum;    //2
		}

		else if (TheSum < 0)
		{
			TheSum = 0;    //3
		}
	}
}

为什么这段代码能够成功找到目标值呢?我们可以通过下面这个例子来理解:

用户输入:
4 -3 5 -8 7 6 2 -1

我们重点分析一下 i=3 的时候函数中发生了什么。
首先执行语句1,TheSum 由6变成了-2,接着执行语句3,将 TheSum 置零。
为什么要这么做呢,理由很简单:

B中不必可能含有-8(原因将稍后解释)

换言之,-8这个元素将整个数列分成了两部分,其中一部分是-8左侧的子列,记为C

4 -3 5

另一部分是-8右侧的子列,记为D

7 6 2 -1

我们所求的B就只能是C、D以及它们的子列中的一个。显然,在这道题里,D就是我们要找的B。

而为什么B中一定没有-8呢?
不妨让我们这样理解寻找目标子列的过程:

4 -3 5 -8 7 6 2 -1
该数列等价于
1 5 -8 7 6 2 -1(4和-3加在了一起)
进而
6 -8 7 6 2 -1
进而
-2 7 6 2 -1(数列的最左侧是负数)
截止目前, MaxSum 中储存的数据是6

在我们寻找目标子列时,我们有时会选择性的把负数加到我们的子列当中,因为我们期待着在负数后面我们可以遇到一个绝对值更大的正数,这样就能让子列最终的元素和变大。但是有一种情况下负数是一定不能加入到子列中的——那就是负数在数列的最左侧的情况。而-8的出现就造成了这种情况,因此我们只得以-8为间断点将数列分成两部分再来寻找目标子列。

把-2抛弃后
7 6 2 -1
进而
13 2 -1(由于 13>6 ,MaxSum 的数据更新)
进而 
15 -1
进而
14
此时 MaxSum=14
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值