问题描述:即求数组中和最大的连续子数组
方法一:分治法
将数组A以mid为界分成左右两个相同大小的子数组,则任一子数组在A[0..mid]、A[mid+1..A.length]和跨过mid,两端分别在[0..mid]和[mid+1..A.length]中;这3种情况之一
依据这个可以设计递归方法,其中最重要的是:
1、分别从mid向左寻找和最大的点i,从mid+1向右寻找和最大的点j,则A[i..j]即为跨过中点的最大子数组
2、最后选择左,中,右3者中的最大子数组和最大的返回
typedef struct sum_str{//定义一个结构体便于传参
int start;
int end;
int sum;
}str_sum;
void getmax_divide(int * A,str_sum *p){//分治法
//通过p传进来start和end,传回去最大子数组的start,end,sum,这样避免了动态内存分配
if(p->start>=p->end){
p->sum=A[p->start];
return;
}
int mid=(p->start+p->end)/2;
str_sum left={p->start,mid,0};//左边的递归调用[0..mid]
getmax_divide(A,&left);
str_sum right={mid+1,p->end,0};//右边的递归调用[mid+1..end]
getmax_divide(A,&right);
int i,tep,maxsum_left,maxsum_right,sum=0;//下面计算穿过mid的最大子数组
for (i=mid+1,tep=i,maxsum_right=A[i],sum=0;i<=p->end;i++){//从mid+1向右遍历,记录最大子数组
sum+=A[i];
if(maxsum_right<sum){
tep=i;
maxsum_right=sum;
}
}
p->end=tep;
for (i=mid,tep=i,maxsum_left=A[i],sum=0;i>=p->start;i--){//从mid向左遍历,记录最大子数组
sum+=A[i];
if(maxsum_left<sum){
tep=i;
maxsum_left=sum;
}
}
p->start=tep;
p->sum=maxsum_left+maxsum_right;//左右的sum加在一起,为穿过mid的最大子数组
str_sum *t;
if(p->sum>=left.sum && p->sum>=right.sum){//选出3者中最大的返回去
return;
}else if(left.sum>=right.sum && left.sum>=p->sum){
t=&left;
}else t=&right;
p->start=t->start;
p->end=t->end;
p->sum=t->sum;
}
这里有T(n)=2*T(n/2)+Θ(n) => T(n)=Θ(n*lgn) 注:这里lgn为log(2)(n)
方法二、动态规划
int getmax_dynamic(int * A,int n){//动态规划中的方法
int maxsum=A[n-1];
int st=n-1,ed=n-1,tep=n-1;
int sum=0;
while(--n>=0){
sum+=A[n];
if(sum>maxsum){
maxsum=sum;
st=n;
ed=tep;
}
if(sum<0){
sum=0;
tep=n-1;
}
}
cout << st <<":"<<ed<<":"<<maxsum<<endl;
return maxsum;
}
最后利用随机数方法对两个方法测试:
void init(int *a,int &n){//初始化数组的数据,用于测试
srand(n);
do{
n=int(rand()%len)+1;
}while(!n);
int i=0;
for (i=0;i<n;i++){
a[i]=rand()%span-span/2;
}
}
int main(){
int n=0;
int A[len];
/*
cout<<"input n:";
n=0;
while(cin>>A[n]) n++;
if(n<=0) return 0;
*/
while(1){
init(A,n);
cout << endl << "********************************************************************\n";
for (int i=0;i<n;i++)
cout << A[i] << " ";
cout <<endl << n <<endl;
int kepp=getmax_dynamic(A,n);
str_sum t={0,n-1,0};
getmax_divide(A,&t);
cout<<t.start<<":"<<t.end<<":"<<t.sum<<endl;
if(t.sum!=kepp) break;//当两种方法结果不同时就表示有一个出错了
}
return 0;
}
完整的代码文件为:http://download.csdn.net/detail/haohaohaoxu/9753563
不足之处欢迎指正。