1. 题目描述:
给出一个长度为N的序列:a1,a2,……,an,求最大连续和。找到1=<I<=J<=N,使得ai+a(i+1)+……+aj尽量大。(若最大连续和为负数,保留之,不必替换为0。)
2. 算法1
1) 思路解析:枚举所有可能的子序列的和,通过三重循环每次求出一个数组下标范围为[index1, index2]的子序列的和,每次求出和后进行判断,更新最大值。
2) 时间复杂度O(N^3);空间复杂度O(1)
代码:
void ON3(int test[],int arraysize)
{
int thissum,maxsum=-INF;//初始化最大值为负无穷
for(int index1=0; index1<arraysize; index1++)//枚举子序列的起点下标
{
for(int index2=index1; index2<arraysize; index2++)//枚举子序列的终点下标
{
thissum=0;
for(int index3=index1; index3<=index2; index3++)//求[index1,index2]子序列的和
{
thissum=thissum+test[index3];
}
maxsum=max(maxsum,thissum);// 更新最大值
}
}
cout<<"最大连续和为:"<<maxsum<<endl;
}
3. 算法2
1) 思路解析:基本同算法1,改进在于去掉第三层循环,第二层循环枚举子序列的终点下标时,每次枚举都进行依次累加,thissum不在第二层循环内清空,减少了部分重复的计算。
2) 时间复杂度O(N^2);空间复杂度O(1).
代码:
void ON2(int test[],int arraysize)
{
int thissum,maxsum=-INF;
for(int index1=0; index1<arraysize; index1++)
{
thissum=0;
for(int index2=index1; index2<arraysize; index2++)
{
thissum=thissum+test[index2];
maxsum=max(maxsum,thissum);
}
}
cout<<"最大连续和为:"<<maxsum<<endl;
}
4. 算法3
1) 思路解析:采取分治法。我们从满足结果的子序列的特性进行分析。假如把序列分成左半部分和右半部分,那么最大子序列和可能在三处出现。或者是整个出现在左半部分,或者是整个出现在右半部分,或者是横跨左右两部分。对于前两种情况可以递归求解,对于第三种情况,可以先求出左半部分的最大和(包含左半部分的最后一个元素)以及右半部分的最大和(包含右半部分的第一个元素),然后再把两个和相加得到。最后取这三个最大值中的最大值即可。主程序中调用ONlogN(testarray , 0 , arraysize-1)即可。
2) 时间复杂度O(NlogN);空间复杂度O(1).时间复杂度分析:
设T(N)为求解大小为N的最大子序列和问题所花费的时间。显然T(1)=1;否则,程序必须得运行两次递归(每个递归的程序的运行时间为T(N/2),