您的位置:首页 > 其它

最大连续子数组和(算法导论算法实现)

2018-01-28 16:51 417 查看
啊啊啊啊啊!算法导论关于这部分类容的讲解在分治策略的第一节。然而网易公开课上本书的配套mit课程里的老师并没有讲,可能人家觉得不值得讲吧。

核心算法

对于给定的数组,取其中点,记ans=-inf,先从中点向左延伸,不断求和,每求和一次就更新一下ans使其成为最大,记下使ans最大的点为left。再从中点向右延伸求和,更新另一个和最大值ans,记下使其最大的那个点right。最终,跨越中点的子数组就是从left到right的所有元素。

核心算法修正

修正算法使得当数组数量很少时结果依然正确,比如当数组只有一个元素时结果为它本身

分治

最考验脑力的地方是这里的理解

简单来说,假如一个数组只含有a,b两个元素,那么总的最大和应为max({a,b},a,b)即:整个数组跨越中点的值,左边元素,右边元素,这些中的最大值。而左边元素的值恰好是其本身跨越其中点的最大值,右边元素也是其本身跨越其中点的最大值。因为我们先对算法做了修正。

这个时候,我们发现,对于四个元素,我们只需要将左右两边的最大值分别当成新数组的元素,这个新数组仅仅包含了两个最大值为元素。

不难发现,无论数组多大,只要能够将其分解为两个以下元素的小数组,就能通过max函数和层层迭代求得整个答案。

理解我的代码需要注意的地方

数组作为函数参数。

显然数组不能直接作为参数,所以我用到了指针。用指针来传递数组元素时,元素的内存地址必须是连续的,所以我又用malloc函数来实例化我的数组。

数组的输入

本次输入的数组没有事先说明元素的个数。如果先造一个大数组实在浪费,虽有vector,但它的性质向来很差劲,不仅不能和数组一样得心应手,还常常溢出,不到万不得已我一般不用。这次我先用一个队列装下所有元素,然后根据队列的长度来造一个数组,在把队列的元素装入新数组中。

其他的内容可以对着算法导论上的伪代码观看。

代码

//跨越中点的最大子数组和
#include<cstdio>
#include<string>
#include<queue>

#include<stdlib.h>
#define INF 0x3f

using namespace std;

int maxn(int a,int b,int c)
{
return max(max(a,b),c);
}

int Max_Crossing(int *Array,int low,int high)
{
int N=high-low+1,ans=0;
if(high==low) return Array[low];
int mid=(N+1)/2;
int left_sum=-INF,sum=0,max_left=mid;
for(int i=mid;i>=low;i--)
{
sum+=Array[i];
if(sum>left_sum) {sum=left_sum;max_left=i;}
}
mid=N/2;
int right_sum=-INF,max_right=mid+1;sum=0;
for(int j=mid+1;j<=high;j++)
{
sum+=Array[j];
if(sum>right_sum) {right_sum=sum;max_right=j;}
}
for(int h=max_left;h<=max_right;h++) ans+=Array[h];
return ans;
}

int Max_All(int *Array,int low,int high)
{
int MMax=0;
if(low<high)
{
int mida=(low+high)/2;
MMax=maxn(Max_All(Array,low,mida),Max_All(Array,mida+1,high),Max_Crossing(Array,low,high));
}
else MMax=Max_Crossing(Array,low,high);
return MMax;
}

int main()
{
int key,N=0;
queue<int>import;
while(scanf("%d",&key)!=EOF)
{
N++;
import.push(key);
}
int *Array=(int*)malloc(sizeof(int)*(N+1));//定义并初始化Array
for(int i=1;i<=N;i++)
{
key=import.front();
import.pop();
Array[i]=key;
}
printf("%d\n",Max_All(Array,1,N));
return 0;
}


嗯,感谢您的耐心观看。有什么问题可以留言哦!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: