#include<stdio.h>
int main()
{
int K,max=0,now=0;
scanf("%d",&K);
int a[K];
int i=0,j=0;
for(;i<K;i++)
scanf("%d",&a[i]);
max+=a[0];
for(i=0;i<K-1;i++)
{
now=a[i];
for(j=i+1;j<K;j++)
{
now+=a[j];
if(now>max)
{
max=now;
}
}
}
printf("%d",max);
return 0;
}
看到这道题。。我首先想到的是2个for遍历所有可能性。然后继续看书。。
算法1
int
MaxSubsequenceSum(const int A[],int N)
{
int ThisSum,MaxSum=0,i,j,k;
for(i=0;i<N;i++)
{
for(j=i;j<N;j++)
{
ThisSum=0;
for(k=i;k<=j;j++)
{
ThisSum+=A[k];
}
if(ThisSum>MaxSum)
MaxSum=ThisSum;
}
}
return MaxSum;
}
这才是真正的遍历了所有可能性,k在i到j之间,算出了所有可能性,时间开销为o(N^3)
算法2
int
MaxSubsequenceSum(const int A[],int N)
{
int ThisSum,MaxSum=0,i,j,k;
for(i=0;i<N;i++)
{
ThisSum=0;
for(j=i;j<N;j++)
{
ThisSum+=a[j];
if(ThisSum>MaxSum)
MaxSum=ThisSum;
}
}
return MaxSum;
}
这个算法就跟我写的一样了
算法3
int
MaxSum(const A[],int Left,int Right)
{
int MaxLeftSum,MaxRightSum;
int MaxLeftBorderSum,MaxRightBorderSum;
int LeftBorderSum,RightBorderSum;
int Center ,i;
Center=(Left+Right)/2;
MaxLeftSum=MaxSum(A,Left,Center);
MaxRightSum=MaxSum(A,Center+1,Right);
MaxLeftBorderSum=0;LeftBorderSum=0;
for(i=Center;i>=Left;i--)
{
LeftBorderSum+=a[i];
if(LeftBorderSum>MaxLeftBorderSum)
MaxLeftBorderSum=LeftBorderSum;
}
MaxRightBorderSum=0;RightBorderSum=0;
for(i=Center+1;i<=Right;i++)
{
RightBorderSum=0;
if(RightBorderSum>MaxRightBorderSum)
MaxRightBorderSum=RightBorderSum;
}
return Max(MaxLeftSum,MaxRightSum,MaxLeftBorderSum+MaxRightBorderSum);//比较函数
}
int
MaxSubsequenceSum(const int A[],int N)
{
return MaxSum(A,0,N-1);
}
把数字分成2部分,那么最大子序列的可能性有3种:
1在左半部分,2在右半部分,3在左右中间,(此时一定包括左半部分的最右数字,右半部分的最左数字
1和2用递归,3直接遍历求
O(NlogN)
算法4
int
MaxSubsequenceSum(const int A[])
{
int ThisSum,MaxSum;
int i;
ThisSum=0;MaxSum=0;
for(i=0;i<N;i++)
{
ThisSum+=A[i];
if(ThisSum>MaxSum)
MaxSum=ThisSum;
else if(ThisSum<0)
ThisSum=0;
}
return MaxSum;
}
这个算法变态了。就用了一个循环
如果ThisSum不如MaxSum,而且ThisSum是负数,那么继续下去没有意义了,后面及时是正的还得抵消前面负数的值
所以使得ThisSum归零重新开始寻找