最大连续子数组和(算法导论算法实现)
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,但它的性质向来很差劲,不仅不能和数组一样得心应手,还常常溢出,不到万不得已我一般不用。这次我先用一个队列装下所有元素,然后根据队列的长度来造一个数组,在把队列的元素装入新数组中。
其他的内容可以对着算法导论上的伪代码观看。
嗯,感谢您的耐心观看。有什么问题可以留言哦!
核心算法:
对于给定的数组,取其中点,记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; }
嗯,感谢您的耐心观看。有什么问题可以留言哦!
相关文章推荐
- 算法导论之最大子数组问题 C语言实现
- [算法导论-分治策略]求最大子数组之各种解法及源代码实现
- 获得连续子数组的最大和(见算法导论第三版第三章)
- 算法导论 4.1-5 最大子数组问题 线性时间算法 C++简单实现
- 算法导论4.1-3~4.1-5最大子数组暴力算法和递归算法的实现和线性时间算法实现
- [算法导论]练习4.1-5最大连续子数组问题
- 算法导论之动态规划之最大子数组
- 面试题,求一个整数数组中和最大的连续子数组,例如:[1, 2, -4, 4, 10, -3, 4, -5, 1]的最大连续子数组是[4, 10, -3, 4](需写明思路,并编程实现)
- 连续子数组的最大和java实现
- 算法导论-第12章-二叉搜索树:随机二叉搜索树数据结构C++实现(前中后序遍历,插入,搜索,前后毗邻元素,最大最小值)
- 【算法拾遗】三种方法求连续子数组的最大和
- 算法学习之路:分治策略-最大子数组-java实现
- 动态规划--求最大连续子数组的和(Python实现)&求解最大连续乘积字串(Python实现)
- 4.1最大数组问题(算法导论)
- 算法学习-连续子数组求和最大值
- Java实现算法之--求子数组和的最大值
- 【算法导论】最大子数组问题
- 【算法导论学习-007】最大子数组和问题(Maximum subarray problem)
- C++最大堆实现priority_queue优先级队列(算法导论)
- 【算法导论】10.1-5单数组实现双端队列