关于最大子序列求和O(n)阶算法的理解
2018-02-12 13:30
232 查看
看到数据结构与算法分析(c语言描述)第二章,关于子序列之和的O(n)阶算法,有点难理解,书里面也没有讲明白。网上看了2~3篇博客,总算有点明白了,自己整理一下,以便以后再遇到类似问题的时候可以翻出来看看快速理解。
书上源码:int MaxSubsequenceSum(const int A[],int N)
{
int ThisSum,MaxSum,j;
ThisSum=MaxSum=0;
for(j=0;j<N;j++)
{
ThisSum+=A[j];
if(ThisSum>MaxSum)
MaxSum=ThisSum;
elseif(ThisSum<0)
ThisSum=0;
}
return MaxSum;
}关于这段源码,主要有两个问题需要理解:
1.最大子序列和为什么可以是:对数组元素一直累加过程中的最大值
A[0]>0,A[0]+A[1]>0,A[0]+A[1]+ A[2]>0,,,,,,A[0]+A[1]+........+A[p-1]>0。但是A[0]+A[1]+........+ A[p-1]+ A[p]<0。说明 p这个位置,是A数组的元素累加和过程中遇到的第一个小于零的位置。
那么对于在区间[0,p-1]的任意位置k,由于A[0]+ A[1]........A[s]>0 ( s∈(0,k] )且A[0]+ A[1]........A[p]<0,可以给出结论:A[0]+A[1]+........+A[k]>A[s]+........+ A[k]:既0~k位置的元素累加和大于任意s~k位置的子序列之和(图1)。
因为s和k的位置具有在区间[0,p-1]之间的任意性,因此对数组A顺序累加这个过程其实已经遍历了0~p-1之间的所有的子序列的和(注意是子序列的和,并没有遍历0~p-1之间所有子序列),然后if(ThisSum>MaxSum) MaxSum=ThisSum;该语句已经在这个过程中记录了0~p-1之间的所有的子序列的和的最大值。
图12.为什么当数组累加和小于零时,可以在当前位置的下一个位置,即A[p+1]的位置重新累加
elseif(ThisSum<0) ThisSum=0;语句说明,当元素累加时遇到第一个位置p,使得A[0]+A[1]+........+ A[p-1]+ A[p]<0时,可以从p+1的位置开始,重新开始这个累加过程。为什么可以这样呢?
此时所有的子序列可以认为分成3种情况:
第1种情况是p之前所有的子序列(既0~p-1之间的所有子序列,已由前面求得0~p-1之间最大子序列的和,存在MaxSum中)。
第2种情况是p之后所有的所有子序列(暂时还未求得)。
第3种情况是包含p这个位置的子序列。
先来考虑一下第3种情况下的子序列:这个子序列的是:
A[m]+........ A[p-1]+ A[p]+ A[p+1]+ ........+ A
,其中m∈[0,p-1],n∈[p+1,N-1]。
由于A[0]+ A[1]........A[m-1]>0,A[0]+ A[1]........A[p]<0,则说明A[m]+........ A[p-1]+ A[p]<0,见图2。所以p位置之后的子序列A[p+1]+........+ A
只要带上p+1之前的子序列A[m]+........ A[p-1]+ A[p],就会变得更小了。因此舍去m~p位置的子序列,可以从p+1位置处重新开始累加A[p+1]+........+ A
, n∈[p+1,N-1]。这就回到了上述第2种情况的子序列,因此这时只需要计算p之后所有的所有子序列之和的最大值。
图2
书上源码:int MaxSubsequenceSum(const int A[],int N)
{
int ThisSum,MaxSum,j;
ThisSum=MaxSum=0;
for(j=0;j<N;j++)
{
ThisSum+=A[j];
if(ThisSum>MaxSum)
MaxSum=ThisSum;
elseif(ThisSum<0)
ThisSum=0;
}
return MaxSum;
}关于这段源码,主要有两个问题需要理解:
1.最大子序列和为什么可以是:对数组元素一直累加过程中的最大值
A[0]>0,A[0]+A[1]>0,A[0]+A[1]+ A[2]>0,,,,,,A[0]+A[1]+........+A[p-1]>0。但是A[0]+A[1]+........+ A[p-1]+ A[p]<0。说明 p这个位置,是A数组的元素累加和过程中遇到的第一个小于零的位置。
那么对于在区间[0,p-1]的任意位置k,由于A[0]+ A[1]........A[s]>0 ( s∈(0,k] )且A[0]+ A[1]........A[p]<0,可以给出结论:A[0]+A[1]+........+A[k]>A[s]+........+ A[k]:既0~k位置的元素累加和大于任意s~k位置的子序列之和(图1)。
因为s和k的位置具有在区间[0,p-1]之间的任意性,因此对数组A顺序累加这个过程其实已经遍历了0~p-1之间的所有的子序列的和(注意是子序列的和,并没有遍历0~p-1之间所有子序列),然后if(ThisSum>MaxSum) MaxSum=ThisSum;该语句已经在这个过程中记录了0~p-1之间的所有的子序列的和的最大值。
图12.为什么当数组累加和小于零时,可以在当前位置的下一个位置,即A[p+1]的位置重新累加
elseif(ThisSum<0) ThisSum=0;语句说明,当元素累加时遇到第一个位置p,使得A[0]+A[1]+........+ A[p-1]+ A[p]<0时,可以从p+1的位置开始,重新开始这个累加过程。为什么可以这样呢?
此时所有的子序列可以认为分成3种情况:
第1种情况是p之前所有的子序列(既0~p-1之间的所有子序列,已由前面求得0~p-1之间最大子序列的和,存在MaxSum中)。
第2种情况是p之后所有的所有子序列(暂时还未求得)。
第3种情况是包含p这个位置的子序列。
先来考虑一下第3种情况下的子序列:这个子序列的是:
A[m]+........ A[p-1]+ A[p]+ A[p+1]+ ........+ A
,其中m∈[0,p-1],n∈[p+1,N-1]。
由于A[0]+ A[1]........A[m-1]>0,A[0]+ A[1]........A[p]<0,则说明A[m]+........ A[p-1]+ A[p]<0,见图2。所以p位置之后的子序列A[p+1]+........+ A
只要带上p+1之前的子序列A[m]+........ A[p-1]+ A[p],就会变得更小了。因此舍去m~p位置的子序列,可以从p+1位置处重新开始累加A[p+1]+........+ A
, n∈[p+1,N-1]。这就回到了上述第2种情况的子序列,因此这时只需要计算p之后所有的所有子序列之和的最大值。
图2
相关文章推荐
- 算法之最大子序列求和
- 关于最大流 Dinic 算法的一些理解。
- 关于二分图最大匹配--匈牙利算法的理解
- 关于子序列最大和的几种算法
- 最大子序列求和算法二三
- 数组复习及Scanner类 ,及对最大值,最小值、平均数、求和等基本算法的理解
- 数据结构和算法学习系列之最大子序列求和问题的O(N)时间复杂度
- 【数据结构和算法分析】最大子序列求和问题及联机算法
- 最大子序列和算法
- 最大连续子序列求和详解
- 【算法竞赛入门经典】8.1 最大连续子序列和
- 关于SIFT算法中:“精确的关键点定位”的理解
- 最大子序列的和算法三分析
- 算法之最大连续子序列之和之变形题目
- 算法-蓝桥杯-入门训练 序列求和 (JAVA)
- 算法的艺术--最大子序列和问题
- OFBiz entity engine 关于数据库自增序列生成算法的源码解读
- 关于 HTTP GET/POST 请求参数长度最大值的一个理解误区
- Max Subsequence Sum 最大子序列和问题 O(NlogN)与O(N)算法的对比
- 求最大连续子序列和4种算法解析