[算法]最大子段和问题
2016-03-13 14:56
253 查看
给定长度为n的整数序列,a[1…n], 求[1,n]某个子区间[i , j]使得a[i]+…+a[j]和最大.或者求出最大的这个和.例如(-2,11,-4,13,-5,2)的最大子段和为20,所求子区间为[2,4].
通过三重循环遍历所有的子段可能,取得最大和时的子段下标,简单但低效,并且当序列范围太大时,可能会超时。
但是我们可以通过优化O(n^3)的穷举代码,消除第三个循环,使它变成O(n^2)复杂度。
分治
考虑到子段区间[begin,end]可能存在的情况有三种:
位于[0,n/2]区域内
位于[n/2+1,n-1]区域内
起点位于[0,n/2]区域内,终点位于[n/2+1,n-1]区域内
那么最后的结果只能是上述三种结果中的最大值,所以可以利用分治的思想,前两种情况使用递归方法,第三种情况使用穷举法求出。
这种分治的方法复杂度是O(nlog n),可以满足大多数样例。
- 动态规划
这里引用一段网上对该问题的动态规划的分析:
解题思路
穷举通过三重循环遍历所有的子段可能,取得最大和时的子段下标,简单但低效,并且当序列范围太大时,可能会超时。
int begin = 0; int end = 0; int max_sum = 0; for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { int sum = 0; for (int k = i; k <= j; k++) { sum += array[k]; } if (sum > max_sum) { max_sum = sum; begin = i; end = j; } } }
但是我们可以通过优化O(n^3)的穷举代码,消除第三个循环,使它变成O(n^2)复杂度。
int begin = 0; int end = 0; int max_sum = 0; for (int i = 0; i < n; i++) { int sum = 0; for (int j = i; j < n; j++) { sum += array[j]; if (sum > max_sum) { max_sum = sum; begin = i; end = j; } } }
分治
考虑到子段区间[begin,end]可能存在的情况有三种:
位于[0,n/2]区域内
位于[n/2+1,n-1]区域内
起点位于[0,n/2]区域内,终点位于[n/2+1,n-1]区域内
那么最后的结果只能是上述三种结果中的最大值,所以可以利用分治的思想,前两种情况使用递归方法,第三种情况使用穷举法求出。
int maxSub(int* n, int left, int right) { if (left == right) return n[left]>0?n[left]:0; int mid = (left+right)/2; int leftSub = maxSub(n,left,mid); int rightSub = maxSub(n,mid+1,right); int sum = 0; int leftMax = 0; //向左边扩散 for (int i = mid; i >= left; i--) { sum += n[i]; if (sum > leftMax) { leftMax = sum; } } sum = 0; int rightMax = 0; //向右边扩散 for (int i = mid+1; i <= right; i++) { sum += n[i]; if (sum > rightMax) { rightMax = sum; } } int ans = leftMax + rightMax; ans = max(max(ans,leftSub),max(ans,rightSub)); return ans; }
这种分治的方法复杂度是O(nlog n),可以满足大多数样例。
- 动态规划
这里引用一段网上对该问题的动态规划的分析:
int* b = new int[n+1]; memset(b,0,n+1); for (int i = 1; i < n+1; i++) { if (b[i-1] > 0) { b[i] = b[i-1]+a[i]; } else { b[i] = a[i]; } } return max(b ,0);
相关文章推荐
- 外联css及js的使用
- RecyclerView一个奇怪的npe异常
- CSS3详解:transform
- HDU1151最小路径覆盖
- HTML5的革新——语义化标签
- MySQL双主热备问题处理
- SpringMVC+Mybatis框架整合java源码 maven mysql
- Python分布式学习(2)
- HDU.1019Least Common Multiple【深搜求最小公倍数】(3.13)
- uva104 (DP + floyd)
- python之网络编程学习小结
- 让你的JS更优雅的小技巧
- C语言中的数组和指针以及字符串
- java程序设计基础_陈国君版第五版_第八章例题
- 纯JavaScript在网页上实现”简书“的文章编辑器
- 二、MyBatis的常用基本知识
- 初学者 ffmpeg + SDL2.0 安装与应用概要点
- 线程的创建-4
- laravel开发环境准备
- 第三周项目二-本月有几天?