最大子序列和问题
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语言描述》