求最大连续子向量之和
来源:互联网 发布:linux服务器禁止ping 编辑:程序博客网 时间:2024/05/19 19:39
问题引出
《编程珠玑》第8章引出一个模式识别问题:输入是具有n个浮点数的向量x,输出是输入向量的任何连续子向量中的最大和。例如:
31 -41 59 26 -53 58 97 -93 -23 84
那么应该输出想x[2..6]的综合,即187。
分析
当所有书都是正数时,问题很容易解决,此时最大子向量就是整个输入向量。当输入向量中有负数的时候,是否应该包含某个负数并期望旁边的正数会弥补它呢?这里定义当所有输入都是负数的时候,总和最大的子向量是空向量,总和为0。
解决
1.平方算法
即对任何的正数对(i,j),计算x[i..j]的总和,求出最大总和。对于输入规模n来书,需要执行O(n2)步。
int MaxSum1(int *a,int n){int maxsofar = 0;int sum;for(int i = 0;i < n;i++){sum = 0;for(int j = i;j < n;j++){sum = sum + a[j];maxsofar = maxsofar>sum?maxsofar:sum;}}return maxsofar;}
2.分治算法
分治原理:要解决规模为n的问题,可递归地的解决俩个规模近似为n/2的子问题,然后对它们的答案进行合并并得到整个问题的答案。
在本例中,初始问题要处理大小为n的向量,所以将它划分为两个大小近似相等的子向量a,b,然后递归地找出a,b中元素总和最大的子向量,分别为ma,mb。要注意这时候,最大子向量要么在整个a中(即ma),要么在整个b中(即mb),要么跨越a和b之间的边界。我们将跨越边界的最大子向量称为mc。
那么如何计算mc?mc在a中的部分是包含右边界的最大子向量,在b中的部分是包含左边界的最大子向量。
所以最终递归计算ma和mb,并且通过上诉方法计算mc,然后返回3个总和中的最大者。
int max(int a,int b){return a>b?a:b;}int MaxSum2(int *a,int l,int u){if(l == u)//一个元素return max(0,a[l]);int m = (l+u)/2;int lmax,rmax,sum;lmax = sum = 0;for(int i = 0;i >= l;i--){sum = sum + a[i];lmax = max(lmax,sum);}rmax = sum = 0;for(int i = m+1;i <= u;i++){sum = sum + a[i];rmax = max(rmax,sum);}return max(lmax+rmax,max(MaxSum2(a,l,m),MaxSum2(a,m+1,u)));}该算法实在每层递归中都执行O(n)次操作,而总计有O(logn)层递归,所以所需时间为O(nlogn)。
3.扫描算法
可以采用一种类似动态规划的算法,从数组的最左端开始扫描,一直到最右端为止,并记下所遇到的总和最大的子向量。假设我们已经解决了x[0..i-1]的问题,那么前i个元素中,最大总和子数组要么在前i-1个元素中(我们将其存储在maxsofar中),要么其结束位置为i(我们将其存储在maxendinghere中)。
int MaxSum3(int a[],int n){int maxsofar = 0;int maxendinghere = 0;for(int i = 0;i < n;i++){maxendinghere = max(0,maxendinghere + a[i]);maxsofar = max(maxsofar,maxendinghere);}return maxsofar; }该算法的关键在于理解maxendinghere。在循环中的第一个赋值语句之前,maxendinghere是结束位置为i-1的最大子向量的和,赋值语句将其修改为结束位置为i的最大子向量的和。若加上a[i]之后结果为正,则该赋值语句使maxendinghere增大a[i];若加上a[i]后结果为负,则该赋值语句将maxendinghere重设为0。其运行时间为O(n)。
- 求最大连续子向量之和
- 求最大连续子数组之和
- 求最大连续子数组之和
- 求数组中任何连续子向量之和
- 求数组的连续子数组之和最大
- 求最大连续子序列之和 立方算法
- 动态规划--求最大连续子串之和
- 模式识别-查找向量中元素之和最大的连续子向量
- 模式识别-查找向量中元素之和最大的连续子向量---编程珠玑
- 求最大连续子向量和-编程珠玑
- 最大连续子序列之和
- 最大连续子列之和
- 最大连续子列之和
- 最大连续子序列之和
- 最大连续子序列之和
- 最大连续子序列之和
- 最大连续子序列之和
- 最大子连续序列之和
- HDU 1395 2^x mod n = 1
- (Android开发)Eclipse中如何恢复已删除文件
- scikit-learn(工程中用的相对较多的模型介绍):1.13. Feature selection
- HDOJ 1097 A hard puzzle(规律)
- VirtualBox 中 Ubuntu 硬盘容量扩大
- 求最大连续子向量之和
- 2005年GCT真题
- 2015.8.7记录iOS侧滑实现
- leetcode_Palindrome Linked List
- 234 - Palindrome Linked List
- CocoaPods安装和使用和遇到的坑
- POJ 1026 Cipher 置换群
- 菜鸟程序员如何防止上错船
- UVa 11054 Wine trading (贪心)