蓝桥杯 算法提高 和最大子序列



  算法提高 和最大子序列  
时间限制:1.0s   内存限制:512.0MB
    
问题描述
  对于一个给定的长度为N的整数序列A,它的“子序列”的定义是:A中非空的一段连续的元素(整数)。你要完成的任务是,在所有可能的子序列中,找到一个子序列,该子序列中所有元素的和是最大的(跟其他所有子序列相比)。程序要求你输出这个最大值。
输入格式
  输入文件的第一行包含一个整数N,第二行包含N个整数,表示A。
  其中
  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;
}
简直完美!!! 数组都不要用了,节省空间和时间。可惜有很大的局限性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值