最大子序列和问题 分治算法
来源:互联网 发布:mac 卸载java jdk 编辑:程序博客网 时间:2024/05/15 04:37
问题:给定整数A1,A2,·······,An,求该序列中所有子序列(包括本序列)中的元素和最大值,如果所有整数均为负数,则最大子序列和为0
算法一:穷举法。运行时间为O(N3)
代码:
int MaxSubsequenceSum(const int A[], int N){int ThisSum, MaxSum, i,j,k;MaxSum = 0;for(i = 0; i< N; i++){for(j = i; j < N; j++){ThisSum = 0;for(k = i; k <= j; k++)ThisSum += A[k];if(ThisSum > MaxSum)MaxSum = ThisSum;}}return MaxSum;}
算法二:撤销算法一的一个for循环,运行时间O(N2)
代码:
int MaxSubsequenceSum(const int A[], int N){int ThisSum, MaxSum, i,j,k;MaxSum = 0;for(i = 0; i < N; i++){ThisSum = 0;for(j = i; j < N; j++){ThisSum += A[j];if(ThisSum > MaxSum)MaxSum = ThisSum;}}return MaxSum;}
算法三:分治算法,相对复杂度的O(NlogN)解法
把问题分成两个大致相等的子问题,然后递归的对它们求解,这是“分”部分。“治”阶段将两个子问题的解合并到一起并可能再做一些少量的附加工作,最后得到整个问题的解。
在本题中,最大子序列和可能在三处出现。或者整个出现在输入数据的左半部分,或者整个出现在右半部分,或者跨越输入数据的中部从而占据左右两半部分。前两种情况可以递归求解, 第三种情况的最大和可以通过求出前半部分的最大和(从前半部分的最后一个元素开始查找,必须包含最后一个元素的序列)以及后半部分的最大和(包含后半部分的第一个元素)而得到。然后这两个和加在一起。
代码:
int Max3(int Left, int Right, int Center){cout<<"Left = "<<Left<<'\t'<<"Right = "<<Right<<'\t'<<"Center = "<<Center<<endl;if(Left > Right){if(Left > Center)return Left;elsereturn Center;}elseif(Right > Center)return Right;elsereturn Center;}static int MaxSubSum(const int A[], int Left, int Right){int MaxLeftSum, MaxRightSum;int MaxLeftBorderSum, MaxRightBorderSum;int LeftBorderSum, RightBorderSum;int Center, i;if(Left == Right)if(A[Left] > 0)return A[Left];elsereturn 0;Center = (Left +Right)/2;MaxLeftSum = MaxSubSum(A, Left, Center);MaxRightSum = MaxSubSum(A, Center+1, Right);/** 处理在Center两边交叉的元素可能构成的最大子序列和的可能* 求出左半部分从Center元素开始,向左寻找子序列的最大和 MaxLeftBorderSum* 求出有半部分从Center + 1开始的,向右寻找子序列的最大和 MaxRightBorderSum* 然后将 MaxLeftBorderSum + MaxRightBorderSum 就是在Center两边交叉元素可能构成的最大子序列的和*/MaxLeftBorderSum = 0;LeftBorderSum = 0;for(i = Center; i >= Left; i--){LeftBorderSum += A[i];if(LeftBorderSum > MaxLeftBorderSum)MaxLeftBorderSum = LeftBorderSum;}MaxRightBorderSum = 0;RightBorderSum = 0;for(i = Center + 1; i <= Right; i++){RightBorderSum += A[i];if(RightBorderSum > MaxRightBorderSum)MaxRightBorderSum = RightBorderSum;}return Max3(MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum);}int MaxSubsequenceSum(const int A[], int N){return MaxSubSum(A, 0, N - 1);}
算法四:直接判断,若前一个子序列的和小于 0, 则按和为0计算
代码:
int MaxSubsequenceSum(const int A[], int N){int ThisSum, MaxSum, i;ThisSum = MaxSum = 0;for(i = 0; i < N; i++){ThisSum += A[i];if(ThisSum > MaxSum)MaxSum = ThisSum;elseif(ThisSum < 0)ThisSum = 0;}return MaxSum;}
补充:当所有元素全是负数时要求也是求出最大的和,应该改成这样:
int max_sub_array_sum2(int* array, int len){if(array == NULL || len < 0)exit(1);int max_sum = array[0];int cur_sum = array[0];for(int i=1; i < len; i++){cur_sum += array[i];if(cur_sum < array[i]){cur_sum = array[i];} if(cur_sum > max_sum){max_sum = cur_sum;}}return max_sum;}
- 最大子序列和问题 分治算法
- 算法导论-分治、最大子序列问题
- 算法导论-分治、最大子序列问题
- 算法导论-分治、最大子序列问题
- 最大子序列和分治算法
- 最大子序列和的分治算法
- 求序列中最大子序列和(分治算法)
- [算法学习笔记]分治法——最大子序列和问题
- 分治法求最大子序列和问题
- 最大子序列和问题 算法
- [算法]最大子序列和问题
- 算法2:最大子序列和问题
- 【算法】最大子序列和问题
- 分治问题,求最大子序列HDU1231
- BJFU1274 最大子序列和(分治)
- 分治法求最大子序列和
- 借助 求 一个序列中最大和子序列 学习 分治算法 code in C#
- 最大子段问题 分治算法
- Spring攻略笔记-6 外部化Bean配置
- UVA 11991
- 改进的hibernate工具类
- ibatis传递日期Date参数
- menuconfig过程详解
- 最大子序列和问题 分治算法
- gameloft 2013.06月 C++笔试题
- 常用的键值搜录
- Linpack使用Infiniband网络计算时内存分配问题
- double-array trie 译文+心得
- 代码重构方法
- web前端
- Android类库打包方法探究
- sublime text 3 的管理插件:package control