求解最大子数组问题的三种方法
来源:互联网 发布:淘宝阿里妈妈在哪里 编辑:程序博客网 时间:2024/05/20 05:59
求解最大子数组问题的三种方法
标签(空格分隔): 算法 分治 最大子数组
算法导论中有这样一个例子来引出最大子数组问题:
在股市中,人们为了获取更大利益,希望“低价买进,高价卖出”,从而获得最大收益。然而,简单的以最低价格买入,最高价格卖出并不能获得最大收益。我们可以不直接观察每日股票的价格,而是考虑每日股票的价格变化值。第
- 输入:数组
A={13,−3,−25,20,−3,−16,−23,18,20,−7,12,−5,−22,15,−4,7} - 输出:最大子数组的和 43
暴力解法
- 算法思想
枚举数组中所有连续子序列的和,并求出其中的最大值。 代码
int max_sub_array_tolient(int a[],int n){int this_sum;int max_sum = 0;for(int i=0;i<n;i++){ for(int j=i;j<n;j++){ this_sum = 0; for(int k = i;k<=j;k++){ this_sum += a[k]; if(this_sum>max_sum) max_sum = this_sum; }}}return max_sum;}
算法分析
很明显,上述代码嵌套三层循环,需要的时间复杂度为O(n3) .
- 算法思想
分治解法
分治法(divide andconquer)是一种基于多分枝递归的算法范式。顾名思义,分治就是“分而治之”,即将原问题分解为两个或多个子问题,直到分解为不能分解的子问题,然后将这些问题合并成原问题的解。- 算法思想
假设我们要寻找A[low...high] 的最大子数组。我们需要将子数组划分为两个规模大致相等的子数组。即我们将数组A[low...high] 划分为A[low...mid] 和A[mid+1...high] ,其中mid=(low+high)/2 。那么,A[low...high] 中所有连续子数组A[i...j] 所处的位置一定是下面三种情况之一。- 完全位于子数组
A[low...mid] 中,其中,low<=i<=j<=mid 。 - 完全位于子数组
A[mid+1...high] 中,其中,mid+1<=i<=j<=high - 既位于子数组
A[low...mid] ,又位于A[mid+1...high] 中,其中low<=i<=mid<=j<=high .
- 完全位于子数组
- 算法思想
由上述知,最大子数组必然位于子数组
跨越中点的子数组一定由
- 代码
int max_sub_array(const int a[],int left,int right){ if(left == right){ if(a[left]>0) return a[left]; else return 0; } int mid = (left+right)/2; //recursion int max_sum_left = max_sub_array(a,left,mid); int max_sum_right = max_sub_array(a,mid+1,right); int left_sum = 0; int sum = 0; for(int i = mid;i>=left;i--){ sum += a[i]; if(sum>left_sum) left_sum = sum; } int right_sum = 0; sum = 0; for(int i = mid+1;i<=right;i++){ sum += a[i]; if(sum>right_sum) right_sum = sum; } return max(max_sum_left,max_sum_right,left_sum+right_sum);}
- 算法分析
现在我们来分析上述算法的时间复杂度。假设总的耗费时间为T(n) 。
由上述代码,第2~8行耗费常数时间,即O(1) 。第10~11行,求解n/2 个元素的子数组所耗费的时间为T(n/2) 。第13~27行,求解跨越中点(mid) 的最大子数组的时间复杂度为O(n) .所以,T(n)=O(1)+2T(n/2)+O(n) 。最后,求解该递归式,得时间复杂度为O(nlgn) 。
- online algorithm
利用online algorithm的思想,可以在线性时间内求得这个问题的解。
算法思想:
从数组第一个元素开始,扫描数组,记录到目前为止处理过的最大数组。若已知
A[1...j] 的最大子数组,那么,下一步求A[1...j+1] 的最大子数组。此时,有两种情况:A[1...j+1] 的最大子数组就是A[1...j] 的最大子数组;
A[1...j+1] 的最大子数组为某个子数组A[i...j+1](1<=i<=j+1) 。
在知道
代码
int max_subarray_online(int a[],int n){int max_sum = 0;int this_sum = 0;for(int j = 0;j<n;j++){ this_sum += a[j]; if(this_sum>max_sum){ max_sum = this_sum; }else if(this_sum < 0){ this_sum = 0; }}return max_sum;}
算法分析
很明显,上述算法的时间复杂度为
参考资料
1:Introduction to Algorithms
[2]:Data Structures and Algorithm Analysis in C[2]:Introduction to Algorithms
- 求解最大子数组问题的三种方法
- 求解PTA最大子列和问题的三种方法(包括输出首尾项)
- 求解最大子数组问题
- 求解最大子数组问题
- 三种算法求解一个数组的子数组最大和
- 三种算法求解一个数组的子数组最大和
- 三种算法求解一个数组的子数组最大和
- 三种算法求解一个数组的子数组最大和
- 三种算法求解一个数组的子数组最大和
- 最大子数组问题的三种方法:分治法、暴力法和非递归方法
- 【算法学习】最大子数组问题的分治法求解
- 最大子数组问题的分治求解算法
- 三种方法求最大连续子数组的和
- 三种方法求最大连续子数组的和
- 三种方法求连续子数组的最大和
- 三种方法求连续子数组的最大和
- Python实现求解最大子数组问题
- 分治法求解最大子数组问题
- Quartz 2D学习(二)绘制曲线
- kvc机制与kvc的常用方法
- 我的JAVA之路(一)
- mybatis注解详解
- SQL语句的分类
- 求解最大子数组问题的三种方法
- MAC 下安装MATLAB2014b
- MyEclipse_环境搭建
- linux驱动platform平台设备总线
- 【我的成长之路——英语】——good luck charlie
- mybatis使用注解2
- 乘坐公交
- android端使用hessian跟服务器通讯
- stm32学习笔记——GPIO