最大子序列问题

输入一组整数,求出这组数字子序列和中最大值。也就是只要求出最大子序列的和,不必求出最大的那个序列。例如:

序列:-2 11 -4 13 -5 -2,则最大子序列和为20

序列:-6 2 4 -7 5 3 2 -1 6 -9 10 -2,则最大子序列和为16

    

1.对这个问题,有一个相对复杂的O(NlogN)的解法,就是使用递归。该方法我们采用分治策略divide-and-conquer)。

在我们例子中,最大子序列可能在三个地方出现,或者在左半部,或者在右半部,或者跨越输入数据的中部而占据左右两部分。前两种情况递归求解,第三种情况的最大和可以通过求出前半部分最大和(包含前半部分最后一个元素)以及后半部分最大和(包含后半部分的第一个元素)相加而得到。

//递归法,复杂度是O(nlogn) 
long maxSumRec(const vector<int>& a, int left, int right) 
{ 
       if (left == right) 
       { 
              if (a[left] > 0) 
                     return a[left]; 
              else 
                     return 0; 
       } 
       int center = (left + right) / 2; 
       long maxLeftSum = maxSumRec(a, left, center); 
       long maxRightSum = maxSumRec(a, center+1, right); 
 
       //求出以左边对后一个数字结尾的序列最大值 
       long maxLeftBorderSum = 0, leftBorderSum = 0; 
       for (int i = center; i >= left; i--) 
       { 
              leftBorderSum += a[i]; 
              if (leftBorderSum > maxLeftBorderSum) 
                     maxLeftBorderSum = leftBorderSum; 
       } 
 
       //求出以右边对后一个数字结尾的序列最大值 
       long maxRightBorderSum = 0, rightBorderSum = 0; 
       for (int j = center+1; j <= right; j++) 
       { 
              rightBorderSum += a[j]; 
              if (rightBorderSum > maxRightBorderSum) 
                     maxRightBorderSum = rightBorderSum; 
       } 
 
       return max3(maxLeftSum, maxRightSum,  
              maxLeftBorderSum + maxRightBorderSum); 
} 
 
long maxSubSum3(const vector<int>& a) 
{ 
       return maxSumRec(a, 0, a.size()-1); 
}

 

2.

下面介绍一个线性的算法,这个算法是许多聪明算法的典型:运行时间是明显的,但是正确性则很不明显(不容易理解)。全部为负数的情况,特殊处理。

//线性的算法O(N) 

long maxSubSum4(const vector<int>& a) 

{ 

       long maxSum = 0, thisSum = 0; 

       for (int j = 0; j < a.size(); j++) 

       { 

              thisSum += a[j]; 

              if (thisSum > maxSum) 

                     maxSum = thisSum; 

              else if (thisSum < 0) 

                     thisSum = 0; 

       } 

       return maxSum; 

}

 

posted on 2013-03-19 14:43  在大地画满窗子  阅读(294)  评论(0编辑  收藏  举报