最大子序列和问题
来源:互联网 发布:软件开发工作流程图 编辑:程序博客网 时间:2024/05/18 01:14
问题描述:
int main(int argc, char **argv){ vector<int> a;a.push_back(-2);a.push_back(11);a.push_back(-4);a.push_back(13);a.push_back(-5);a.push_back(-2);int result;result = maxSubSum1(a); //在这里更改调用的函数名 cout<<result<<endl; //正确结果为 20 return 0;}
方法一:对所有的子序列求和,在其中找到最大的
int maxSubSum1( const vector<int> &a ){ int maxSum = 0;for(int i=0; i<a.size(); i++ ){ for(int j=i; j<a.size(); j++ ){ int thisSum =0;for( int k=i; k<=j; k++ ){ thisSum += a[k]; }if(thisSum>maxSum){ maxSum = thisSum;}}}return maxSum;}
分析:
另一种思路:上面的方法在每一次循环中,固定i,并把a[i]当做起点,下面的方法将a[i]当做终点。
int maxSubSum1_2( const vector<int> &a ){ int maxSum = 0; for(int i=0; i<a.size(); i++ ){ for(int j=0; j<i; j++ ){ int thisSum =0; for(int k=j; k<=i; k++){ thisSum +=a[k]; //从节点j开始 累加到节点iif(thisSum>maxSum){ maxSum = thisSum; }}}}return maxSum; }
方法二:从某点开始的所有序列中,找最大的
int maxSubSum2( const vector<int> &a ){ int maxSum = 0;for(int i=0; i<a.size(); i++ ){ int thisSum =0;for(int j=i; j<a.size(); j++ ){ thisSum +=a[j]; //从节点i开始 累加到结尾if(thisSum>maxSum){ maxSum = thisSum; }}}return maxSum;}
分析:
注意:下面是一个错误的方法,因为它的起始点固定了,每次都从a0开始,是不能保证遍历所有的子序列的。
int maxSubSum2_2( const vector<int> &a ){ int maxSum = 0; for(int i=0; i<a.size(); i++ ){ int thisSum =0;for(int j=0; j<=i; j++ ){ thisSum +=a[j]; //从节点0开始 累加到节点iif(thisSum>maxSum){ maxSum = thisSum; }}}return maxSum;}
如果希望将固定终点,那么计算的时候就要从终点开始,依次往前累加。代码如下:
int maxSubSum2_3( const vector<int> &a ){ int maxSum = 0; for(int i=0; i<a.size(); i++ ){ int thisSum =0;for(int j=i; j>=0; j-- ){//从节点i开始,向前累加到结尾0thisSum +=a[j];if(thisSum>maxSum){ maxSum = thisSum; }}}return maxSum;}
方法三:从某一个正数开始
第一步:
int maxSubSum3_1( const vector<int> &a ){ int maxSum = 0;for(int i=0; i<a.size(); i++ ){ //(相对方法2,新增)如果a[i]<=0,那么a[i]一定不是所要求的起点,所以直接跳过去(利用for循环中有i++)if( a[i]<=0 ) continue;int thisSum =0;for(int j=i; j<a.size(); j++ ){ thisSum +=a[j];if(thisSum>maxSum){ maxSum = thisSum; }}}return maxSum;}
第二步:
int maxSubSum3_2( const vector<int> &a ){ int maxSum = 0;for(int i=0; i<a.size(); i++ ){ //(相对方法2,新增)如果a[i]<=0,那么a[i]一定不是所要求的起点,所以直接跳过去(利用for循环中有i++)if( a[i]<=0 ) continue;int thisSum =0;for(int j=i; j<a.size(); j++ ){ thisSum +=a[j];if(thisSum>maxSum){ maxSum = thisSum; }else if( thisSum <= 0 ){ //(相对方法3_1 新添) thisSum = 0; i = j; }}}return maxSum;}
第三步:
int maxSubSum3_3( const vector<int> &a ){ int maxSum = 0;for(int i=0; i<a.size(); i++ ){ //(相对方法2,新增)如果a[i]<=0,那么a[i]一定不是所要求的起点,所以直接跳过去(利用for循环中有i++)if( a[i]<=0 ) continue;int thisSum =0;for(int j=i; j<a.size(); j++ ){ thisSum +=a[j];if( thisSum>0 ){ //(相对方法3_2 新添)if(thisSum>maxSum){ maxSum = thisSum; }i = j; //(相对方法3_2 新添)}else if( thisSum <= 0 ){ //(相对方法3_1 新添) thisSum = 0; i = j;}}}return maxSum;}
第四步:
最后如果你又了解一些程序结构上的优化的知识,那么你会发现下面的问题:
① 循环的分支可以改变一下,去除嵌套分支结构。
② 判断语句的分支中有共同部分,( i=j ),可以抽取出来。
以上两步以后,循环部分的代码编程 变成:
for(int i=0; i<a.size(); i++ ) { if( a[i]<=0 ) continue; int thisSum =0; for(int j=i; j<a.size(); j++ ) { thisSum +=a[j]; if(thisSum>maxSum) { maxSum = thisSum; } else if( thisSum>0 ) { //do nothing } else if( thisSum <= 0 ) { thisSum = 0; } i = j; } }
③ 下面这步非常重要,如果你发现,内层循环的循环变量j 和 外层循环的循环变量i
到这里,代码就可以神奇的变为如下的形式:常量空间,线性时间
int maxSubSum3_4( const vector<int> &a ) { int maxSum = 0; int thisSum = 0; for(int j=0; j<a.size(); j++ ) { thisSum += a[j]; if(thisSum>maxSum) { maxSum = thisSum; } else if( thisSum>0 ) { //do nothing } else if( thisSum < 0 ) { thisSum = 0; } } return maxSum; }
分析:
- 最大和子序列问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题~~
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- AIO 磁盘异步I/O
- 面试训练排序
- poj 3469 Dual Core CPU
- 我们是酷毕(苦逼)程序员!--------持续更新。
- MySQL_02
- 最大子序列和问题
- 软件开发文档之概述
- .Net企业级应用架构设计之UML
- tomcat安全设置
- 面试训练斐波那契数列
- 为什么转置一个512x512的矩阵,会比513x513的矩阵慢很多?
- Wireshark中文版抓包工具
- C# word or excel Convert to PDF
- tomcat 的server.xm配置详解