0.分治永远大于顺序?关于最大子序列和问题的思考
Posted clclcl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了0.分治永远大于顺序?关于最大子序列和问题的思考相关的知识,希望对你有一定的参考价值。
p17. 2.4.3 最大子序列和的问题的解
题目:给定整数A1,A2,......,AN,求∑k=i~jAk的最大值(如果所有整数都为负数,则最大子序列和为0)
书中给出了四种不同的算法,时间复杂度依次降低,下面我简单描述一下这四种算法
第一种:穷举法
求出所有子序列和,比较得出最大的
最简单想到的代码,效率十分低下,原因是没有利用数列的连贯性,对数列元素反复检索造成浪费
三层嵌套循环,时间复杂度
T(N)=O(N3)
int Maxsubsum(const int A[],int N) { int ThisSum,Maxsum,i,j,k; Maxsum=0; for(i=0;i<N;i++) //确定各个子序列的首项 for(j=i;j<N;j++) //确定每个序列的元素个数 { ThisSum=0; for(k=i;k<=j;k++) /*开始按照确定的元素个数选出数列并计算子列和,较大者覆盖Maxsum,较小者在ThisSum中被丢弃*/ ThisSum += A[k]; if(ThisSum>Maxsum) Maxsum=ThisSum; } return Maxsum; }
第二种:改良后的穷举法
顾名思义,这种方法对方法一进行了改良.
当第选定了子序列的首项后,无需对子序列长度进行再次分组,直接顺序列出所有该首项下的子数列即可,减去了一次循环。
实际上换汤不换药
时间复杂度依旧为幂函数级
T(N)=O(N2)
int Maxsubsum(const int A[],int N) { int ThisSum,Maxsum,i,j,k; Maxsum=0; for(i=0;i<N;i++)//确定各个子序列的首项 { ThisSum=0; for(k=i;k<=j;k++)/*开始按照确定的元素个数选出数列并计算子列和,较大者覆盖Maxsum,较小者在ThisSum中被丢弃*/ { ThisSum += A[k]; if(ThisSum>Maxsum) Maxsum=ThisSum; } } return Maxsum; }
第三种:分治法
这是我们今天着重要探讨的第一种算法。
先上代码。
1 #include "stdio.h" 2 int 3 MaxSubSum(const int A[],int left,int right)//left,right分别为数列数组第一个元素和最后一个元素的下标 4 { 5 int Maxleftsum,Maxrightsum; 6 int Maxleftbordersum,Maxrightbordersum; 7 int leftbordersum,rightbordersum; 8 int Center,i; 9 10 if(left==right) /*base case*/ 11 if(A[left]>0) 12 return A[left]; 13 else 14 return 0; 15 16 17 Center=(left+right)/2; 18 Maxleftsum=MaxSubSum(A,left,Center); 19 Maxrightsum=MaxSubSum(A,Center+1,right); 20 21 Maxleftbordersum=0;leftbordersum=0; 22 for(i=Center;i>=left;i--) 23 { 24 leftbordersum +=A[i] 25 if(leftbordersum>Maxleftbordersum) 26 Maxleftbordersum=leftbordersum; 27 } 28 29 Maxrightbordersum=0;rightbordersum=0; 30 for(i=Center+1;i<=right;i++) 31 { 32 rightbordersum +=A[i] 33 if(rightbordersum>Maxrightbordersum) 34 Maxrightbordersum=rightbordersum; 35 } 36 37 return Max(Maxleftbordersum,Maxrightbordersum,Maxrightbordersum+Maxleftbordersum) 38 39 }
看起来可能有些复杂哈,我第一次看也是半天看不懂,没有这方面的基础。
我们先来看一个简单的问题来理解啥叫分治。
以上是关于0.分治永远大于顺序?关于最大子序列和问题的思考的主要内容,如果未能解决你的问题,请参考以下文章
算法设计与分析--求最大子段和问题(蛮力法分治法动态规划法) C++实现