max=b1[j];}
return max;
}
算法5,其实用代码实现并不难,难的是思想。算法5int MAX_SUM(int a[],int i,int j)
{
int k,s1,l,temp; //s1用来存储当前子段的s[i,l-1]的最大子段和
s1=0;temp=0; //temp用来与s1比较,判断是否此时的s1是最大子段
for(l=i;l<=j;l++)
{
temp=temp+a[l];
if(temp>=s1)
s1=temp;
else
if(temp<=0) //{
break;
}
}
if(l>=j) //子 return s1;
if(l==i) //当temp小于等于0,找到l的值,跳出循环
如果l等于j,或者l等于j+1,则s[i,l-1]的最大段s1就是s[i,j]的最大子段和
如果l等于i,则最大子段在s[i+1,j],递归计
算。 问题规模减少1。
return MAX_SUM(a,l+1,j);
else //如果ireturn MAX(s1,MAX_SUM(a,l+1,j));}补:取出所给序列的所有子序列求和,先分n组比较这n(n+1)/2个序列的和,再将每组的最大值比较,从而得到最大值以及其上下标。
a1 a2 an-1 an
a1+a2 a2+a3 an-1+an
a1+a2+a3 a2+a3+a4 ......
...... ......
a1+a2......+an a2+a3......+an
此算法比较直接,也容易写出代码,但其时间开销为O(n2),空间开销为O(n),效率不高。
现在想出来的算法时间代价是O(n),空间代价是常数(主要指辅助空间的开销,而a1a
2......an的开销不算在内)。
当然此算法每上一个算法那么直接,写代码也麻烦一些,具体如下:
1. 从左向右寻找在序列中出现的第一个非负整数,如果找不到即全为负数,返回最大序列值为0,否则执行2。
2. 将起下标赋给besti,并将第besti个数作为最大子序列和S的初值。
3. 下游标k的初值为besti+1,下游k寻找到下一个非负整数,计算besti到k子段的值记为Sik。
4. 比较S,Sik以及第k个整数的值:当S最大时,将besti赋值给下标bestj;当Sik最大时,将Sik赋值给S,将k赋值给下标bestj;当第k个整数的值最大时,其值赋给S,besti的值改写为k,将besti的值赋给bestj。
5.下游k,如果k<=n,转从3开始执行,否则返回最大子序列和S,算法结束。
第二种算法的实现代码
#includevoid main()
{
int n,i,j;
int MaxSum(int n, int* a, int& besti, int& bestj);
cout<<\"输入序列长度(必须为正整数):\"<cin>>n;int* a=new int[n];
cout<<\"输入\"<for(i=0;icin>>a[i];int S=MaxSum(n,a,i,j);
cout<cout<<\"i=\"<delete []a;}
int MaxSum(int n, int* a, int& besti, int& bestj)
{
bestj=besti=0; //初始化上下标
int k=besti+1; //初始化子段的下游标
int Sik=0;
while(a[besti]<0 && bestiif(besti==n) return 0; // 如果全部是负数,返回最大子段值为0int S=a[besti];//当前最大子段和
while(kwhile(a[k]<0 && k//计算i—k子段的和Sik=0;
for(int i=besti; i<=k; i++ )
Sik += a[i];
//下面的3个分之语句为此算法的关键
if(a[k]>=Sik && a[k]>=S) //下游标对应的值最大时
{
bestj=besti=k; //当前所求的子段上下标均为k
S=a[k];//当前所求子段和为a[k]
}
else if(Sik>=a[k] && Sik>=S)//i—k子段的和最大时
{
S=Sik; //当前所求子段和为
bestj=k; //当前所求子段下标为k
}
else if(S>=a[k] && S>=Sik) bestj=besti; //当前最大子段和为a[besti],下标为besti
k++;//下游标继续下游
}
return S;//返回非0的最大子段和
}
//atlantis 的代码,基本思想就是正数、负数序列分别求和,一遍扫描完成。
#include #include #include using namespace std;
template struct result_node {
size_t start;
size_t end;
T value;
};
struct result_max {
bool operator() (const result_node x,const result_node y) const {return x.value < y.value;
}
};
template void maxSubQueue(vector ia, vector >& aVector, size_t n){
size_t itor = 0;
int postSeq = 0;
int negSeq = 0;
int StartIndex = 0;
int LastIndex = 0;
result_node rn;while (itor != n) {
while(itor != n && ia[itor] < 0)
negSeq += ia[itor++];
if (postSeq + negSeq < 0) {
StartIndex = LastIndex = itor;
postSeq = negSeq = 0;
continue;
}
else postSeq += negSeq;
while(itor != n && ia[itor] >= 0)
postSeq += ia[itor++];
LastIndex = itor-1;
if (StartIndex <= LastIndex) {
rn.start = StartIndex;
rn.end = LastIndex;
rn.value = postSeq;
aVector.push_back(rn);
}
}
}
int main() {
int seq[] = {-2, 2, 3, 8, -5, -7, 5, 14, -21, 13, 6, 23, -41, 43};
vector ia(seq, seq+14);vector > aVector;maxSubQueue(ia, aVector, ia.size());
result_node rn = (*max_element(aVector.begin(), aVector.end(), result_max()));
cout << rn.start << \" \" << rn.end << \" \" << rn.value;
return 0;
}
//求一个整型数组(链)里面子链各数和的最大值
#include #define MAX_NUM_CNT 100
void main()
{
int data[] = {-1,-2,-234,-588,-2875,-273,-923748,-293};
int numCount = sizeof(data)/sizeof(int);
int i = numCount - 1;
int dataR[MAX_NUM_CNT];
dataR[i] = data[i]> 0?data[i]:0;
int tmp;
for(;i> 0;--i){
tmp = i-1;
dataR[tmp] = dataR[i] + data[tmp];
if(dataR[tmp] <0)dataR[tmp] = 0;
}
long maxSum = 0,tmpSum = 0;
for(i=0;i if(maxSumtmpSum += data[i];if(tmpSum < 0) tmpSum = 0;
}
cout < < \"max: \" < }分治算法时间复杂度为N*log N,这个我就不帮你写了,我帮你写个动态规划时间复杂度为O(n),空间复杂度为O(1) ,int A[]即为要查找的数组
#includestruct T{int nMaxSum,nFirst,nLast;};
T MaxSum(int A[],int first,int last);
int main()
{
int A[] = {10,-2,-2,3,4,5};
T t = MaxSum(A,0,sizeof(A) / sizeof(int) - 1);
printf(\"(%d,%d,%d)\\n\
return 0;
}
T MaxSum(int A[],int first,int last)
{
T result = {0,0,0};
int nCurSum = A[first];
int nCurStart = first;
result.nMaxSum = A[first];
result.nFirst = first;
result.nLast = first;
for(int i = first + 1;i <= last;i++)
{
if(nCurSum <= 0)
{
nCurStart = i;
nCurSum = 0;
}
nCurSum += A[i];
if(nCurSum > result.nMaxSum)
{
result.nMaxSum = nCurSum;
result.nFirst = nCurStart;
result.nLast = i;
}
}
return result;
}