【算法设计与分析】6、最大字段和
2014-12-07 19:02
399 查看
/** * 书本:《算法分析与设计》 * 功能:若给定n个整数组成的序列a1, a2, a3, ......an, 求该序列形如ai+a(i+1)+......+an的最大值 * 文件:MaxSum.cpp * 时间:2014年11月30日17:37:26 * 作者:cutter_point */ #include <iostream> using namespace std; //方法一: /* 简单的解决方式时间复杂度是O(n^3) 解决方法就是一般算法 */ //给我一串数字元素,找到最大的字段和的那个字段 //n是这串数字的个数, a是这串数字, besti是最佳的开始加的位置,bestj是最佳的结束位置 int MaxSum(int n, int *a, int& besti, int& bestj) { int sum = 0; //统计得到的最大值,从中选出最大的 for (int i = 1; i <= n; ++i) //从第一个数字开始,到最后一个数 { for (int j = i; j <= n; ++j) //j是表明要在i开始到j的累加范围 { int thissum = 0; //一这个i起始的开始向后加到j的当前这个i之后对应的最大字段和 //开始从i开始往后一个一个的加,并把选到最大的那个字段和 for (int k = i; k <= j; ++k) //重这个i加到j(j这个值每个都会试到) thissum += a[k]; if (thissum > sum) { sum = thissum; //把新的最大值放给要返回的值 besti = i; //最好的起始位置给记住 bestj = j; //最好的结束位置给记住 } } } return sum; //返回最大值 } //方法二: /* 简单的解决方式时间复杂度是O(n^2) 解决方法就是运用一个数学公式i到j的累加 = 第j个数 + 前面的j-1个和 */ //给我一串数字元素,找到最大的字段和的那个字段 //n是这串数字的个数, a是这串数字, besti是最佳的开始加的位置,bestj是最佳的结束位置 int MaxSum2(int n, int *a, int& besti, int& bestj) { int sum = 0; //还是这个是得到最终的结果 //还是从第i个开始向后加j,知道所有的i都得到比较 for (int i = 1; i <= n; ++i) { //这个i对应的最大值是 int thissum = 0; for (int j = i; j <= n; ++j) { thissum += a[j]; //从i开始累加 if (thissum > sum) //只要找到比上一个的sum大的就代入 { sum = thissum; besti = i; bestj = j; } } } return sum; } //方法三: /* 简单的解决方式时间复杂度是O(nlogn) 解决方法就是运用分治递归的方式 就是最优子结构是 a[1:n]的最大字段是a[1:n/2]相同的 a[1:n]的最大字段是a[n/2+1:n]相同的 a[1:n]的最大字段和为i到j的累加,且i和j分别在中点的两端 */ //给我一串数字元素,找到最大的字段和的那个字段 //a里面是这一串数字,left是这串数字的开始位置,right是这串数字的结束位置 int MaxSubSum(int *a, int left, int right) { int sum = 0; //还是用来计数最大值 //如果只有一个数了,那么就开是比0大还是比0小,大就是这个数了,小那么还是不用加了就等于0把 if (left == right) //还有这一步是为了方便递归 sum = a[left] > 0 ? a[left] : 0; else //如果不止一个数的话 { int center = (left + right) / 2; //1、得到左边的最大值 int leftsum = MaxSubSum(a, left, center); //2、得到右边的最大值 int rightsum = MaxSubSum(a, center + 1, right); //3、如果左边和右边夹在一起合成的字段和的话 //用一个数来表示左边正数的和 int s1 = 0; //从右到左得到最大的那个值 int lefts = 0; //依次加上左边的下一个值得和 for (int i = center; i >= left; --i) //从中间向左边叠加,为何和右边的合并所以必须这样加 { lefts += a[i]; //依次加到lefts里面 if (lefts > s1) s1 = lefts; //如果这个加起来的和,从右到左得到最大的那个值 } //右边同上 int s2 = 0; //从左到右得到最大的那个值 int rights = 0; //依次加上右边的下一个值得和 for (int i = center + 1; i <= right; ++i) //从中间向右边叠加,为何和左边的合并所以必须这样加 { rights += a[i]; //依次加到lefts里面 if (rights > s2) s2 = rights; } //第三种方式的和是 sum = s1 + s2; //比较三种方式的大小,选出最大的那个 if (sum < leftsum) sum = leftsum; if (sum < rightsum) sum = rightsum; } return sum; } //迭代结束之后得到最大值的方式 //n是数字的个数,a是这串数字的长度 int MaxSum3(int n, int *a) { return MaxSubSum(a, 1, n); } int main() { int a[] = { 0, -1, 7, -3, -3, 5, -2, 7 }; //得到数组的长度 int n = sizeof(a) / sizeof(*a)-1; int besti = 0, bestj = 0; cout << "这串数字是:" << endl; for (int i = 1; i <= n; ++i) cout << a[i] << " "; cout << endl; cout << "最长字段和是:" << MaxSum(n, a, besti, bestj); cout<< " 从" << besti << "到" << bestj << endl; cout << "最长字段和是:" << MaxSum2(n, a, besti, bestj); cout << " 从" << besti << "到" << bestj << endl; cout << "最长字段和是:" << MaxSum3(n, a)<<endl; return 0; }
相关文章推荐
- 算法设计与分析之-最大子段和 (分治)
- 算法设计与分析题目练习五:求最大值(遗传算法)
- 算法设计与分析不定期更新的日常之最大子段和四种方法
- 高效算法设计_算法分析初步(最大连续和)
- [算法设计与分析]4.1.1递推法(兔子繁殖+最大公约数3种方法)
- java实现算法设计与分析-最大间隙
- [算法设计与分析]3.4.2最大公约数的应用(循环移动数组元素)
- 算法分析与设计实验——最大公约数
- 算法分析与设计-10- 最大子段和的动态规划算法
- 算法设计分析:相邻最大矩形面积
- 【算法设计与分析】最大子段和问题
- 【计算机算法分析】动态规划法——最大字段和问题
- 算法分析与设计
- YUV / RGB 格式分析及快速查表算法设计
- 一串首尾相连的珠子(m个),有N种颜色(N《=10),设计一个算法,取出其中一段,要求包含所有N中颜色,并使长度最短。并分析时间复杂度与空间复杂度。
- 算法分析与设计基础 (清华版)
- 统计数字问题[算法设计与分析]
- 算法设计与分析之递归与分治策略
- 算法分析与设计的作业:“基于FMM的分词系统”
- 算法设计作业;三角形最大和;