最大子序列和问题

  1 #include <iostream>
  2 #include <ctime>
  3 using namespace std;
  4 
  5 /*    最大子序列和问题求解
  6  *    给定数A1, A2, ..., An,求第i个到第j个累积和的最大值。
  7  *    如果所有整数均为负数,则最大子序列和为0
  8  */
  9 
 10 /*
 11  *    方法1:穷举式地尝试所有的可能
 12  */
 13 int maxSubsequenceSum_1(const int A[], int N) {
 14     int thisSum, maxSum, i, j, k;
 15     maxSum = 0;
 16     for(i = 0; i < N; i++)
 17         for(j = i; j < N; j++) {
 18             thisSum = 0;
 19             for(k = i; k <= j; k++)        //    出现大量不必要的计算,被过分地耗时
 20                 thisSum += A[k];
 21             if(thisSum > maxSum)
 22                 maxSum = thisSum;
 23         }
 24     return maxSum;
 25 }    //时间复杂度为O(N3)
 26 
 27 int maxSubsequenceSum_2(const int A[], int N) {
 28     int thisSum, maxSum, i, j;
 29     maxSum = 0;
 30     for(i = 0; i < N; i++) {
 31         thisSum = 0;
 32         for(j = i; j < N; j++) {
 33             thisSum += A[j];
 34             if(thisSum > maxSum)
 35                 maxSum = thisSum;
 36         }
 37     }
 38     return maxSum;
 39 }    //时间复杂度O(N2)
 40 
 41 int max3(int a, int b, int c) {
 42     int max;
 43     max = a;
 44     if(b > max)
 45         max = b;
 46     if(c > max)
 47         max = c;
 48     return max;
 49 }
 50 
 51 /*    分治(divide-and-conquer)策略 - 
 52  *    “分”指把问题分成两个大致相等的子问题,然后递归地对它们求解
 53  *    “治”指将两个子问题的解合并到一起并可能再做些少量的附加工作,最后得到整个问题的解
 54  */
 55 int maxSubSum(const int A[], int left, int right) {
 56     int maxLeftSum, maxRightSum;
 57     int maxLeftBorderSum, maxRightBorderSum;
 58     int leftBorderSum, rightBorderSum;
 59     int center, i;
 60 
 61     if(left == right) {    //    只有一个元素时
 62         if(A[left] > 0)
 63             return A[left];
 64         else
 65             return 0;
 66     }
 67 
 68     //    最大子序列和出现在数据的左半部或者右半部,递归求解
 69     center = (left + right) / 2;
 70     maxLeftSum = maxSubSum(A, left, center);
 71     maxRightSum = maxSubSum(A, center+1, right);
 72 
 73     //    最大子序列和占据左右两半部分
 74     //    求出前半部分的最大和(包含前半部分的最后一个元素)
 75     maxLeftBorderSum = 0; leftBorderSum = 0;
 76     for(i = center; i >= left; i--) {
 77         leftBorderSum += A[i];
 78         if(leftBorderSum > maxLeftBorderSum)
 79             maxLeftBorderSum = leftBorderSum;
 80     }
 81     //    求出后半部分的最大和(包含后半部分的第一个元素)
 82     maxRightBorderSum = 0; rightBorderSum = 0;
 83     for(i=center+1; i <= right; i++) {
 84         rightBorderSum += A[i];
 85         if(rightBorderSum > maxRightBorderSum)
 86             maxRightBorderSum = rightBorderSum;
 87     }
 88 
 89     return max3(maxLeftSum, maxRightSum, maxLeftBorderSum+maxRightBorderSum);
 90 }
 91 
 92 int maxSubsequenceSum_3(const int A[], int N) {
 93     return maxSubSum(A, 0, N-1);
 94 }    //    时间复杂度O(NlogN)
 95 
 96 /*    优点:只对数据进行一次扫描,一旦A[i]被读入并被处理,它就不再需要被记忆
 97  *    此外,在任意时刻,算法都能对它已经读入的数据给出序列问题的正确答案 - 联机算法
 98  */
 99 int maxSubsequenceSum_4(int A[], int N) {
100     int thisSum, maxSum, j;
101     thisSum = maxSum = 0;
102     for(j = 0; j < N; j++) {
103         thisSum += A[j];
104         if(thisSum > maxSum)
105             maxSum = thisSum;
106         else if(thisSum < 0)
107             thisSum = 0;
108     }
109     return maxSum;
110 }    //    时间复杂度O(N)
111 
112 int main() {
113     time_t start, end;
114     int A[] = {4, -3, 5, -2, -1, 2, 6, -2, 10, 9, -5, -2, 10, 2, -5, 3};
115     int maxSum;
116 
117     start = clock();
118     maxSum = maxSubsequenceSum_1(A, 16);
119     cout << maxSum << endl;
120     end = clock();
121     cout << 1000.0 * (end - start) / CLOCKS_PER_SEC << endl;    //执行maxSubsequenceSum_1所花费的时间
122 
123     start = clock();
124     maxSum = maxSubsequenceSum_2(A, 16);
125     cout << maxSum << endl;
126     end = clock();
127     cout << 1000.0 * (end - start) / CLOCKS_PER_SEC << endl;
128 
129     start = clock();
130     maxSum = maxSubsequenceSum_3(A, 16);
131     cout << maxSum << endl;
132     end = clock();
133     cout << 1000.0 * (end - start) / CLOCKS_PER_SEC << endl;
134 
135     start = clock();
136     maxSum = maxSubsequenceSum_4(A, 16);
137     cout << maxSum << endl;
138     end = clock();
139     cout << 1000.0 * (end - start) / CLOCKS_PER_SEC << endl;
140 
141     return 0;
142 }

  参考书籍《数据结构与算法分析:C语言描述》

posted @ 2016-07-13 21:09  pestle  阅读(299)  评论(0编辑  收藏  举报