最近在恶补传统的计算机数据结构和算法,发现一个很好的,讲得很细致的课程,就是网易云课堂中的浙江大学的数据结构和算法。以前看过一些数据结构和算法,但是总觉得自己基础很差,现恶补基础,作一定的记录。
问题:给定一个由K个整数(有正有负)组成的序列,求出它的最大子列和。
显然,一眼看上去,可以暴力求解,就是找出所有子列的和,然后注意比较。当然,这种做法的时间复杂度也是很恐怖的,是N^3.
在课程中介绍了对朴素法的一点优化,分治法和在线处理法,我在这里逐一实现。
朴素法的优化
int maxsuq1(int a[], int n)
{
int thissum=0,maxsum=0;
int i,j;
for (i=0;i<n;++i)
{
thissum = 0;
for(j=i;j<n;++j)
{
thissum += a[j];
if (thissum>maxsum)
{
maxsum = thissum;
}
}
}
return maxsum;
}
分治法
// 分治法
int findmax(int a,int b,int c)
{
int m = a;
if(a<b)
m = b;
if(m<c)
m=c;
return m;
}
int DivideCon(int a[], int left, int right)
{
// a[left]到a[right]的总和
int MaxleftSum,MaxrightSum,MaxmidSum;
int center;
if(left == right) // 递归终止标志,左边只有一个数
{
if (a[left]>0)
return a[left];
else
return 0; // 负数则返回0
}
center = (int)(left+right)/2;
MaxleftSum = DivideCon(a,left,center); // 左边最大值
MaxrightSum = DivideCon(a,center+1,right); // 右边最大值
// 跨越中点的最大值
int Maxmidleft=0,Maxmid1=0;
int i;
for(i=center;i>=0;--i)
{
Maxmidleft += a[i];
if(Maxmidleft>Maxmid1)
Maxmid1 = Maxmidleft;
}
int Maxmidright=0, Maxmid2=0;
for(i=center+1;i<=right;++i)
{
Maxmidright+=a[i];
if(Maxmidright>Maxmid2)
Maxmid2 = Maxmidright;
}
return findmax(MaxleftSum, MaxrightSum, Maxmid1+Maxmid2);
}
int Divide(int a[],int len)
{
return DivideCon(a,0,len);
}
在线处理法
// 在线处理法求解
int OnlinePro(int a[],int len)
{
int ThisSum=0,MaxSum=0;
int i;
for(i=0;i<len;++i)
{
ThisSum += a[i];
if (ThisSum>MaxSum)
MaxSum = ThisSum;
else if(ThisSum<0)
ThisSum = 0;
}
return MaxSum;
}
这三种算法,时间复杂度分别为:N^2,NlogN,N