一 写在开头
何为最大子序列和问题?最大子序列和问题可以描述如下:给定一个整数序列A1, A2, ..., AN(可能有负数),试求其存在的一子序列AI, AJ, ...,AM所能达到的最大值(I, J,...,M不一定是相邻的,只要满足I <= J <= ... <= M即可)(为方便起见,如果所有整数均为负数,则其最大子序列和为0)。
1.1 本文内容
求解最大子序列和的几种算法。
二 算法一
算法一是相当直观的枚举算法,其时间复杂度为O(N ^ 3)。主要由算法中的三重for循环达成。其实现如下:
1 int 2 MaxSubsequenceSum(const int a[], int n) 3 { 4 int thisSum, maxSum, i, j, k; 5 6 maxSum = 0; 7 for (i = 0; i < n; i++) 8 for (j = i; j < n; j++) 9 { 10 thisSum = 0; 11 for (k = i; k <= j; k++) 12 thisSum += a[k]; 13 14 if (thisSum > maxSum) 15 maxSum = thisSum; 16 } 17 return maxSum; 18 }
三 算法二
算法二在算法一的基础上去掉了第三重for循环,因此其时间复杂度为O(N ^ 2)。其实现如下:
1 int 2 MaxSubsequenceSum(const int a[], int n) 3 { 4 int thisSum, maxSum, i, j; 5 6 maxSum = 0; 7 for (i = 0; i < n; i++) 8 { 9 thisSum = 0; 10 for (j = i; j < n; j++) 11 { 12 thisSum += a[j]; 13 if (thisSum > maxSum) 14 maxSum = thisSum; 15 } 16 } 17 }
四 算法三
算法三是个递归算法。其每次都将区间一分为二,然后再分别对左右区间递归地进行求解。因为,拥有最大和的子序列要么完全处于左区间,要么完全处于右区间,要么就是左区间的子序列加上右区间的子序列以拼凑成一个和更大的子序列。该算法时间复杂度为O(NlogN),其实现如下:
1 int 2 MaxSubsequenceSum(const int a[], int left, int right) 3 { 4 int maxLeftSum, maxRightSum; 5 int maxLeftBorderSum, maxRightBorderSum; 6 int leftBorderSum, rightBorderSum; 7 int center, i; 8 9 /* base case */ 10 if (left == right) 11 if (a[left] > 0) 12 return a[left]; 13 else 14 return 0; 15 16 center = (left + right) / 2; 17 maxLeftSum = MaxSequenceSum(a, left, center); 18 maxRightSum = MaxSequenceSum(a, center + 1, right); 19 20 maxLeftBorderSum = leftBorderSum = 0; 21 for (i = center; i >= left; i--) 22 { 23 leftBorderSum += a[i]; 24 if (leftBorderSum > maxLeftBorderSum) 25 maxLeftBorderSum = leftBorderSum; 26 } 27 28 maxRightBorderSum = rightBorderSum = 0; 29 for (i = center + 1; i <= right; i++) 30 { 31 rightBorderSum += a[i]; 32 if (rightBorderSum > maxRightBorderSum) 33 maxRightBorderSum = rightBorderSum; 34 } 35 36 return MAX3(maxLeftSum, maxRightSum, maxLeftSum + maxRightSum); 37 }
五 算法四
算法四比较巧妙,而且时间复杂度只有O(N),优于上面的三种算法,其实现如下:
1 int 2 MaxSubsequenceSum(const int a[], int n) 3 { 4 int thisSum, maxSum, i; 5 6 thisSum = maxSum = 0; 7 for (i = 0; i < n; i++) 8 { 9 thisSum += a[i]; 10 if (thisSum > maxSum) 11 maxSum = thisSum; 12 else if (thisSum < 0) 13 thisSum = 0; 14 } 15 return maxSum; 16 }
六 参考资料
1. 《数据结构与算法分析:C语言描述》