最大子序列和问题
问题描述:给定一整数序列A1, A2,... ,An (可能有负数),求A1~An的一个子序列Ai~Aj,使得Ai到Aj的和最大。
分治法:
思路:最大子序列和可能出现在三个地方:整个出现在输入数据的左半部分,整个出现在输入数据的右半部分,或者跨越输入数据的中部从而占据左右两个半部分。
代码:
1 double max3(double a, double b, double c){ 2 int d; 3 d = (a > b) ? a : b; 4 return (d > c) ? d : c; 5 } 6 7 int MaxSubSum(const int A[], int left, int right){ 8 int center = 0; 9 int maxleftsum = 0, maxrightsum = 0; 10 int leftbordersum = 0, rightbordersum = 0; 11 int maxleftbordersum = 0, maxrightbordersum = 0; 12 13 if(left == right) 14 if(A[left] > 0) 15 return A[left]; 16 else 17 return 0; 18 else 19 ; 20 21 center = (left + right) / 2; 22 maxleftsum = MaxSubSum(A, left, center); 23 maxrightsum = MaxSubSum(A, center + 1, right); 24 25 for(int i = center; i >= left; i--){ 26 leftbordersum += A[i]; 27 if(leftbordersum > maxleftbordersum) 28 maxleftbordersum = leftbordersum; 29 } 30 31 for(int i = center + 1; i <= right; i++){ 32 rightbordersum += A[i]; 33 if(rightbordersum > maxrightbordersum) 34 maxrightbordersum = rightbordersum; 35 } 36 37 return max3(maxleftsum, maxrightsum, maxleftbordersum + maxrightbordersum); 38 } 39 40 int MaxSubsequenceSum(const int A[], int N){ 41 return MaxSubSum(A, 0, N - 1); 42 }
动态规划:
思路:在这一遍扫描数组当中,从左到右记录当前子序列的和currentsum,若这个和不断增加,那么最大子序列的和maxsum也不断增加(不断更新maxsum)。如果往前扫描中遇到负数,那么当前子序列的和将会减小。此时currentsum将会小于maxsum,当然maxsum也就不会更新。如果currentsum降到0时,说明前面已经扫描的那一段就可以抛弃了,这时将currentsum置为0。然后,currentsum将从后面开始将这个子段进行分析,若有比当前maxsum大的子段,继续更新max。这样一趟扫描结果也就出来了。
代码:
1 int MaxSubsequenceSum(int a[], int N){ 2 int maxsum = 0, currentsum = 0; 3 for(int i = 0; i < N; i++) 4 { 5 currentsum += A[i]; 6 if(currentsum > maxsum) 7 maxsum = currentsum; 8 else if(currentsum < 0) 9 currentsum=0; 10 } 11 return maxsum; 12 }
作者:longlively —— ONE STEP AT A TIME
出处:http://www.cnblogs.com/longlively/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
posted on 2018-05-17 20:49 longlively 阅读(142) 评论(0) 编辑 收藏 举报