一维向量中连续子向量的最大和

Q:一个一维向量:arr[n] = {i1,i2,i3,......,in} ,计算其连续子向量中最大和。(即截取连续的一段使得段中各元素和最大,元素有负值;子向量可以为空,即和最小为0)

A:

最初的想法是穷举,双层循环将所有连续的元素和算出来

for [i,n){
    for[j,n){
        caculate sum(arr[j],arr[j]);
    }   
}

这种方式虽然有效,但显得很蠢。

这里假设截取的区间是 arr[start, end] ,那么arr[start, end+1]的连续子向量的最大和能不能由arr[start, end]确定?

如果 arr[start, end] 符合条件的子向量(假设其最大和为maxsofar)含最后一个元素,那么arr[start, end+1]只需要看(end+1)这个位置,

如果 arr[start ,end] 符合条件的子向量不含最后一个元素,

那么arr[start, end+1]中符合条件的子向量要么是arr[start ,end]中的那个,要么是包含(end+1)这个元素的新的子向量(其最大和即arr[start,end]中含最后一个元素的最大和maxending+arr[end+1]);

所以对arr[n]有如下代码:

#define N 20
#define MAX(a,b)  (a)>(b)?(a):(b)  
static int maxsofar=0;    //表示arr[start, end]中连续子向量的最大和
static int maxending=0;   //表示arr[start, end]中含(end)元素的最大和
/*static int start = -1;*/ //start的位置暂时没找到好的确定方法
static int end = -1;
void findmax(){ int i=0; for( ; i<N; ++i){ maxending = MAX( maxending+arr[i], 0); //如果arr[start,end]中的maxending加上arr[end+1]小于0,则说明arr[start,end+1]中maxending为0; maxsofar = MAX(maxending,maxsofar); //arr[start,end+1]中的maxsofar为arr[start,end]中maxsofar 和 arr[start,end+1]中maxending的最大值; if(maxsofar==maxending) end = i; } } /*当arr[N] = {-39,45,26,-18,-92,17,-4,68,72,-2,99,4,-67,142,55,-59,19,-41,-72,13};时,输出为 maxsofar=384,end=14;*/

上述实现为线性级,效率比穷举的 n2 级要高很多。

另外,多维向量如何实现(向量间的联系影响到子集的选取)?


           ,          / \         {   }         p   !         ; : ;         | : |         | : |         l ; l         l ; l         I ; I         I ; I         I ; I         I ; I         d | b          H | H         H | H         H I H ,;,     H I H     ,;,;H@H;    ;_H_;,   ;H@H;`\Y/d_,;|4H@HK|;,_b\Y/' '\;MMMMM$@@@$MMMMM;/'   "~~~*;!8@8!;*~~~"         ;888;         ;888;         ;888;         ;888;         d8@8b         O8@8O         T808T          `~` 

posted @ 2015-04-27 01:49  小白干  阅读(180)  评论(0编辑  收藏  举报