关于最大子序列求和O(n)阶算法的理解

     看到数据结构与算法分析(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之间的所有的子序列的和的最大值。

                                         图1

2.为什么当数组累加和小于零时,可以在当前位置的下一个位置,即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[n],其中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[n]只要带上p+1之前的子序列A[m]+........ A[p-1]+ A[p],就会变得更小了。因此舍去m~p位置的子序列,可以从p+1位置处重新开始累加A[p+1]+........+ A[n], n∈[p+1,N-1]。这就回到了上述第2种情况的子序列,因此这时只需要计算p之后所有的所有子序列之和的最大值。

                                        图2

猜你喜欢

转载自blog.csdn.net/carl95271/article/details/79316190
今日推荐