434
社区成员
发帖
与我相关
我的任务
分享伪代码描述:将数组a分成k个小数组,并分别记录每个小数组的和与Max比较,计算完k个小数组的和后k++,继续将a分成k个小数组,并分别记录每个小数组的和与Max比较,以此类推,直到达到停止循环条件k>N,不再划分a数组。(备注:划分每k个小数组时需注意第二个小序列总是从第二个元素开始遍历,第三个小数组总是从第三个元素开始遍历,以此类推,计算完所有划分情况下小数组的和)最后输出最大字段和(最大数组和)Max。
#include <iostream>
using namespace std;
int a[10001],Max,N,i = 1,k = 2,record = 1,sum,times = 0,found = 0;
void MaxSum(int a[])
{
i = 1;//把数组分成每k个的小字段并分别求小子段的和
while(i <= N)
{
sum += a[i++];
times++;
if (times%k == 0) //每当分完k个后做一次sum判断
{ if(sum > Max)
{
Max = sum;
sum = 0;}
sum = 0;
record++;
i = record;
}
}
}
int divide(int a[])
{
if(k <= N)
{
MaxSum(a);//调用函数计算Max
k++;//开始准备分别求每k+1个子段的和
sum=0;//一切清零,重新计算
times = 0;
record = 1;
divide(a);
}
else return 0;
}
int main(){
cin >> N;
for (i = 1;i <= N;i++)
cin >> a[i];
for ( i = 1; i <= N;i++)
if (a[i] > 0) found = 1;
if (found == 0){
cout << 0;
return 0; }
Max = a[1];
for (i = 2;i <= N;i++)
{//先找到数组中最大元素计为max
if (a[i] > Max) Max=a[i];}
i = 1;
divide(a);//调用函数进行划分
cout << Max;
return 0;
}
算法详解:
(1).该算法中待处理数组a元素从下标1开始储存,方便执行后续判断语句if(times%k==0)来完成一次小序列的划分
(2).首先在代码开头指明当数组a中元素全为负数时定义最大字段和Max为0并输出Max,结束返回。
(3).算法中首先将数组a进行一个求和,得到k为1时的最大字段和,并定义为Max,然后k=2,k++依次执行划分,求和,与Max比较的步骤,通过divide函数和MaxSum函数实现。
(4).算法中times为记录元素相加次数,当times==k时,说明一个小数组已划分好,将其sum与最大Max比较,如果比Max大,将此sum赋给Max,否则sum=0继续执行小数组的划分。
(5).算法中的record为记录下一次小数组划分的起始位置,避免漏掉划分情况。
2.分析该算法的时间复杂度
算法划分子问题时间:O(n)
算法求解子问题时间:O(n)
不用合并子问题
时间复杂度:O(n^2)
3.结合本章的学习,你对分治法的体会和思考
分治的基本思想:
把一个复杂的问题分成若干个相似的子问题,并分别求解,最后将子问题的解合并即得原问题的解。
分治法应用:分治可以用递归来实现,也可以不用递归。递归是一种方法,分治是一种思想,虽然分治中递归方法较为常用,实现起来也较为简单,但其效率较低。在应用时当我们发现一个问题可以被分解成若干个问题规模大致相同的子问题时可采用分治法思想求解,同时要注意在算法中摆明结束子问题划分的条件(问题规模是否足够小),避免无限次划分。
实例:归并,快速排序就是很好的例子。将一个数组划分成若干个小数组,再依次求解,最后合并(快速排序不需要合并) 。