输入一个整数数组,数组中有正数也有负数,一个或连续的多个整数组成一个子数组,求所有子数组的和的最大值。
分治法:
#include <iostream>
using namespace std;
//分治法 最大子数组和的问题
// 把一个区间分成两个相等长度的区间
// 该区间的最大子数组有三种可能
// 1.在左区间,不到中点
// 2.在右区间,在中点之后
// 3.跨越中点,一部分在左区间,一部分在右区间
int a[10]={10,2,3,-8,-3,2,7,8,-18,9};//测试
int getMidValue(int *a,int l,int m,int r)
{//第三种情况的求解,跨越中点的
int i,sum=0,max1=a[m],max2=a[m+1];
for(i=m;i>=l;i--)
{//从中点向左边寻找最大子数组
sum+=a[i];
max1=max1<sum?sum:max1;
}
for(i=m+1,sum=0;i<=r;i++)
{//向右边寻找最大子数组
sum+=a[i];
max2=max2<sum?sum:max2;
}
return max2+max1;
}
int fun(int *a,int i,int j)
{
if(i==j) return a[i];
int m=(i+j)/2;
int left=fun(a,i,m);//寻找左区间的最大子数组
int right=fun(a,m+1,j);//寻找右区间
int mid=getMidValue(a,i,m,j);//寻找经过中点的子数组
left=left>right?left:right;
left=left>mid?left:mid;
return left;//返回最大值
}
void main()
{
cout<<fun(a,0,9)<<endl;
}
动态规划:
#include <iostream>
using namespace std;
//动态规划 最大子数组和问题
int fun(int *a,int len)
{
int sum=0,i,t=0;
for(i=0;i<len;i++)
{
if(t>0) t=t+a[i];
else t=a[i];
sum=sum>t?sum:t;
}
return sum;
}
void main()
{
int a[10]={10,2,3,-8,-3,2,7,8,-18,9};
cout<<fun(a,10)<<endl;
}