关于最大子序列和问题的算法设计进化的四个层次

最大子序列和的问题是这样的:Given a sequence S of integer, find the largest sum of a consecutive subsequece of S.(0, if all negative items). 例如,对于序列-2,11,-4,13,-5,-2来说,其最大子序列和是20:(11,-4,13)。

这个问题很简单,但是通过解答这道题可以看出一个人的算法修养有多深。下面详细介绍一下这个问题算法设计的四个层次:O(n^3)->O(n^2)->O(nlgn)->O(n). 为了方便描述,所以使用了伪代码。

 

第一层次:也就是一种brute-force算法,其复杂度为O(n^3),即考虑所有的情况:

     

MaxSum = 0;
for (i = 0; i < N; i++)
	for (j = i; j < N; j++){
		ThisSum = 0;
		for (k = i; k <= j; k++)
			ThisSum += A[k];
			if (ThisSum > MaxSum)
				MaxSum = ThisSum;
	}
return MaxSum;

 

 第二层次:也比较容易想到,其复杂度为O(n^2):

    

 

MaxSum = 0;
  for (i = 0; i < N; i++)
  {
    ThisSum = 0;
    for (j = i; j < N; j++)
    {
      ThisSum += A[j];
      if (ThisSum > MaxSum)
        MaxSum = ThisSum;
    }
  }
  return MaxSum;

 

第三层次:使用Divide-and-Conquer法,其复杂度为O(nlgn),要考虑三种情况:

   

    Center = (Left + Right) / 2;

  MaxLeftSum = MaxSubSum(A, Left, Center);  MaxRightSum = MaxSubSum(A, Center + 1, Right);
  
  MaxLeftBorderSum = 0; LeftBorderSum = 0;
  for (i = Center; i >= Left; i--)
  {
    LeftBorderSum += A[i]; 
    if (LeftBorderSum > MaxLeftBorderSum)    MaxLeftBorderSum = LeftBorderSum;
  }
  
  MaxRightBorderSum = 0; RightBorderSum = 0;
  for (i = Center + 1; i <= Right; i++)
  {
    RightBorderSum += A[i];
    if (RightBorderSum > MaxRightBorderSum)  MaxRightBorderSum = RightBorderSum;
  }
  return Max3(MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum);

 

第四层次:这也是最优算法,用反证法很容易证明,其复杂度为O(n),操作示意如下:

    

   注:第一排记录ThisSum的变化,第二排记录MaxSum的变化,第三排就是给出的序列。

 

ThisSum = MaxSum = 0;
  for (j = 0; j < N; j++)
  {
    ThisSum += A[j];
    if (ThisSum > MaxSum)
      MaxSum = ThisSum;
    else if (ThisSum < 0)
      ThisSum = 0;
  }
  return MaxSum;
 

一斑而可窥全豹,只要一个算法还没有证明是最优的都可以改进,但是对于上面的线性算法来说已是最优的了,可以不必再改了。

你可能感兴趣的:(算法,J#)