算法提高 和最大子序列
时间限制:1.0s 内存限制:512.0MB
问题描述
对于一个给定的长度为N的整数序列A,它的“子序列”的定义是:A中非空的一段连续的元素(整数)。你要完成的任务是,在所有可能的子序列中,找到一个子序列,该子序列中所有元素的和是最大的(跟其他所有子序列相比)。程序要求你输出这个最大值。
输入格式
输入文件的第一行包含一个整数N,第二行包含N个整数,表示A。
其中
1 <= N <= 100000
-10000 <= A[i] <= 10000
其中
1 <= N <= 100000
-10000 <= A[i] <= 10000
输出格式
输出仅包含一个整数,表示你算出的答案。
样例输入
5 3 -2 3 -5 4
样例输出
4
和最大子序列有四种方法
最笨的方法 3重 循环,这种方法绝对超时。
int MaxSubseqSum1(int A[],int N)
{
int ThisSum,MaxSum = 0;
int i,j,k;
for(i=0;i<N;i++)
{
for(j=i;j<N;j++)
{
ThisSum = 0;
for(k=i;k<=j;k++)
{
ThisSum += A[k];
}
if(ThisSum>MaxSum)
{
MaxSum = ThisSum;
}
}
}
//算法复杂度 n的3次方
return MaxSum;
}
稍微改进了一点点 的 方法,二重循环
int MaxSubseqSum2(int A[],int N)
{
int ThisSum,MaxSum = 0;
int 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;
}
第三种,分而治之 法 算法复杂度(O(nlogN)),目前我还不理解 。 哈哈哈哈
int Max3( int A, int B, int C )
{
return A > B ? A > C ? A : C : B > C ? B : C; /* 返回3个整数中的最大值 */
}
int DivideAndConquer( int List[], int left, int right )
{ /* 分治法求List[left]到List[right]的最大子列和 */
int MaxLeftSum, MaxRightSum;
/* 存放左右子问题的解 */
int MaxLeftBorderSum, MaxRightBorderSum;
/*存放跨分界线的结果*/
int LeftBorderSum, RightBorderSum;
int center, i;
if( left == right )
{ /* 递归的终止条件,子列只有1个数字 */
if( List[left] > 0 )
return List[left];
else
return 0;
} /* 下面是"分"的过程 */
center = ( left + right ) / 2;
/* 找到中分点 */ /* 递归求得两边子列的最大和 */
MaxLeftSum = DivideAndConquer( List, left, center );
MaxRightSum = DivideAndConquer( List, center+1, right );
/* 下面求跨分界线的最大子列和 */
MaxLeftBorderSum = 0; LeftBorderSum = 0;
for( i=center; i>=left; i-- ) { /* 从中线向左扫描 */
LeftBorderSum += List[i];
if( LeftBorderSum > MaxLeftBorderSum )
MaxLeftBorderSum = LeftBorderSum;
} /* 左边扫描结束 */
MaxRightBorderSum = 0; RightBorderSum = 0;
for( i=center+1; i<=right; i++ ) { /* 从中线向右扫描 */
RightBorderSum += List[i];
if( RightBorderSum > MaxRightBorderSum )
MaxRightBorderSum = RightBorderSum;
}
/* 右边扫描结束 */ /* 下面返回"治"的结果 */
return Max3( MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum );
}
int MaxSubseqSum3( int List[], int N )
{ /* 保持与前2种算法相同的函数接口 */
return DivideAndConquer( List, 0, N-1 );
}
第四种, 最优算法, 复杂度O(n)
#include <iostream>
using namespace std;
int main()
{
int N,t;
cin>>N;
int ThisSum = 0;
int MaxSum = 0;
for(int i=0;i<N;i++)
{
cin >> t;
ThisSum += t;
if(ThisSum > MaxSum)
{
MaxSum =ThisSum;
}
else if(ThisSum<0)
{
ThisSum = 0;
}
}
cout<<MaxSum;
return 0;
}
简直完美!!! 数组都不要用了,节省空间和时间。可惜有很大的局限性。