子数组之和的最大值

来源:互联网 发布:淘宝宝贝详情要怎么写 编辑:程序博客网 时间:2024/05/20 04:14

         求子数组之和的最大值是一个很经典的问题。问题的描述如下:一个有N个整形数的一维数组(A[0], A[1], ... A[n-1]),这个数组有很多子数组,那么子数组之和的最大值是什么呢?

         这个问题的解答其实在《编程珠玑》一书有的。一共是4中方法:第一种是穷举法,计算所有可能子数组的和,时间复杂度为O(n3)。第二种其实也是穷举法。代码如下

for(i = 0;i < n;i++){ sum = 0; for(j = i;j < n;j++) {  sum += A[j];  if(sum > maxsum)   maxsum = sum; }}


 

         很明显复杂度为O(n2)。第三种方法是分治法,将数组元素均分成两部分,那么最大子数组和只有三种情况。在左边部分,右边部分,以及跨越了边界部分。这种方法是时间复杂度为O(nlogn)。不是最优的就不列代码了。第四种是最优的,时间复杂度为O(n),利用了动态规划的思想。具体代码如下:

int MaxSubSum1(int *A,int n){int start, all;all = start = A[n-1];for(int i = n-2; i >= 0; i--){start = Max(A[i], start + A[i]);all = Max(all, start);}return all;}


 

        这种方法不论是空间和时间都已是最优的了,在《编程之美》中列举了改进的过程,最终的程序就是上面的这段代码。

        如果是二维数组呢,又当如何解答。《编程之美》中给出的解法是穷举矩形区域的所有可能的上下边界,再用一维的方法计算该上下边界的最大和。时间复杂度为 O(n2*m)。当然也可以先穷举矩形区域的所有可能的左右边界。本质上是一样的。下面给出了一种解法。这里用了一个辅助数组B,B[ i ][ j ]表示第 j 列元素的前 i  行元素的和。B[ i + 1 ][ j ]=A[ 0 ][ j ]+A[ 1 ][ j ]+...A[ i ][ j ]。B[ 0 ][ j ]做为哨兵,全部为0。

int MaxSubSum2(int *A, int n, int m)  {      int i, j, k;      //初始化辅助数组      int **B = new int*[n+1];      for(i = 0; i <= n; i++)          B[i] = new int[m];      for(j = 0; j < m; j++)  //第0行做为哨兵          B[0][j] = 0;      for(i = 0; i < n; i++)          for(j = 0; j < m; j++)              B[i+1][j] = B[i][j]+A[i*n+j];      //开始计算      int maxsum = 0x80000000;  //设为最小值      for(i = 1; i <= n; i++)      {          for(j = i; j <= n; j++)          {              int start, all;              start = all = (B[j][m-1]-B[i-1][m-1]);              for(k = m-2; k >= 0; k--)              {                  start = Max(B[j][k]-B[i-1][k], start + B[j][k]-B[i-1][k]);                   all = Max(all, start);              }              if(all > maxsum)                  maxsum = all;          }      }  for(i = 0; i <= n; i++) //释放辅助空间delete [] B[i];delete B;    return maxsum;  }


 

出处 http://blog.csdn.net/wuzhekai1985

原创粉丝点击