/**
* 书本:《算法分析与设计》
* 功能:若给定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;
}
【算法设计与分析】6、最大字段和
最新推荐文章于 2021-06-19 14:16:00 发布
部署运行你感兴趣的模型镜像
您可能感兴趣的与本文相关的镜像
ACE-Step
音乐合成
ACE-Step
ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言
694

被折叠的 条评论
为什么被折叠?



