寻找最大连续子串和
2013-05-20 14:38
274 查看
《编程之美》上的一个经典问题,拿来练习一下
给定一整型数组a[0...n],找出连续子串a[x...y],使得和最大,其中,0<=x<=y<=n。
方法很多,采用动态规划的方法可以达到线性O(n)的时间复杂度。
动态规划需要满足无后效性,分析这个问题,考察数组a[0...m](m<n)的最大连续子串和,有三种可能的情况。
第一:最大的连续子串中不包含a[m],则result[0...m]=result[0...m-1],和前m-1个元素的最大子串和相同。
第二:由包含a[m-1]的前m-1个元素的最大子串和,加上a[m]组成。
第三:由a[m]自己单独组成
假定以a[i]结尾的和最大子串为L[i],那么
L[i]=MAX{a[i],a[i]+L[i]};
result[0...i]=MAX{L[i],max[0...i-1]},即取这三者之中的最大值,满足无后效性。
我们可以定义两个长度为n的数组,一个L[i]用来存储前i个元素中包含a[i]的最大子串和,一个result[i]用来存储前i个元素整体的最大子串和。初始化L[i]=result[i]=a[0],之后从1开始遍历整个数组,采用上面的递推式计算两个数组的值,最后求得result
就是所要的结果。
上述过程还可以进一步简化,因为注意到每次计算L[i],result[i]的时候,实际上只用到了上一步的结果L[i-1],result[i-1],实际上我们不需要存储整个数组,只需存储两个中间变量即可,这样可以把问题的空间复杂度降低到常数级。
上面过程只求出了最大子串和,如果需要最大子串的位置,再引入几个辅助变量,记录其左、右边界,在每次更新result和l的时候,更新它们即可。具体见下面代码(这里把上面所述的记录L的变量记为cur)
下面是几个测试用例
输入
a[]={0,-2,3,5,-1,2};
结果
max=9
from a[2] to a[5]
输入
a[]={1,-2,3,5,-3,2};
结果
max=8
from a[2] to a[3]
输入(输入全为负数的情况也可以正常运行)
a[]={-9,-2,-3,-5,-3,-4};
结果
max=-2
from a[1] to a[1]
给定一整型数组a[0...n],找出连续子串a[x...y],使得和最大,其中,0<=x<=y<=n。
方法很多,采用动态规划的方法可以达到线性O(n)的时间复杂度。
动态规划需要满足无后效性,分析这个问题,考察数组a[0...m](m<n)的最大连续子串和,有三种可能的情况。
第一:最大的连续子串中不包含a[m],则result[0...m]=result[0...m-1],和前m-1个元素的最大子串和相同。
第二:由包含a[m-1]的前m-1个元素的最大子串和,加上a[m]组成。
第三:由a[m]自己单独组成
假定以a[i]结尾的和最大子串为L[i],那么
L[i]=MAX{a[i],a[i]+L[i]};
result[0...i]=MAX{L[i],max[0...i-1]},即取这三者之中的最大值,满足无后效性。
我们可以定义两个长度为n的数组,一个L[i]用来存储前i个元素中包含a[i]的最大子串和,一个result[i]用来存储前i个元素整体的最大子串和。初始化L[i]=result[i]=a[0],之后从1开始遍历整个数组,采用上面的递推式计算两个数组的值,最后求得result
就是所要的结果。
上述过程还可以进一步简化,因为注意到每次计算L[i],result[i]的时候,实际上只用到了上一步的结果L[i-1],result[i-1],实际上我们不需要存储整个数组,只需存储两个中间变量即可,这样可以把问题的空间复杂度降低到常数级。
上面过程只求出了最大子串和,如果需要最大子串的位置,再引入几个辅助变量,记录其左、右边界,在每次更新result和l的时候,更新它们即可。具体见下面代码(这里把上面所述的记录L的变量记为cur)
#include<stdio.h> int main(){ int a[]={0,-2,3,5,-1,2}; int n=6; int result=a[0]; int cur=a[0]; int subl=0,subr=0,tempsubl=0; for(int i=0;i<n;i++){ if(cur>0) cur+=a[i]; else{ cur=a[i]; tempsubl=i; } if(cur>result){ result=cur; subr=i; subl=tempsubl; } } printf("max=%d\n",result); printf("from a[%d] to a[%d]\n",subl,subr); return 0; }
下面是几个测试用例
输入
a[]={0,-2,3,5,-1,2};
结果
max=9
from a[2] to a[5]
输入
a[]={1,-2,3,5,-3,2};
结果
max=8
from a[2] to a[3]
输入(输入全为负数的情况也可以正常运行)
a[]={-9,-2,-3,-5,-3,-4};
结果
max=-2
from a[1] to a[1]
相关文章推荐
- 寻找最大连续子串和
- Java寻找最大连续子串和
- 寻找数组中的最大连续子串
- 寻找最大连续子串和以及寻找最长数字串
- 【Leetcode】寻找数串中连续最大整数和且最大长度的子串
- 【Leetcode】寻找数串中连续最大整数和且最大长度的子串
- 寻找和最大的连续子串
- 1003 最大连续子串和
- 从一个字符串当中找到最大子串(字典序,可以不连续)
- (NYoj 104)最大和 --二维最大连续子串和转化为一维,动态规划
- 编程之法:面试和算法心得(最大连续乘积子串)
- 求和最大的连续子串
- 程序员面试金典:子串判断、 最大连续数列和
- 求和最大的连续子串
- 《算法导论》-最大公共子串(连续) C语言版
- 最大连续乘积子串
- 最大子串和,最长连续子串,最长子序列(不连续)
- N 组连续子串最大和
- [ACM_动态规划] hdu1003 Max Sum [最大连续子串和]
- 在矩阵中寻找最大正方形连续区域