最大子列和问题

最大和子列问题

题目:给定 N N N个整数的序列{ A 1 , A 2 , ⋯   , A N A_1,A_2,\cdots,A_N A1,A2,,AN},求函数 f ( i , j ) = m a x f(i,j)=max f(i,j)=max{ 0 , ∑ k = i j A k 0,\sum_{k=i}^jA_k 0,k=ijAk}的最大值。

算法1

  • 算法复杂度—— T ( N ) = O ( N 3 ) T(N)=O(N^3) T(N)=O(N3)
int MaxSubSum1(int A[], int N);
{
	int ThisSum, MaxSum = 0;		
	int i, j, k;					
	for( i = 0; i< N; i++)			/*i是子列左端位置*/ 
	{
		for( j = i; j < N; j++)		/*j是子列右端位置*/ 
		{
			ThisSum = 0;			/*ThisSum是A[i]到A[j]的子列和*/ 
			for( k = i; k <= j; k++)
				ThisSum += A[k];
			if( ThisSum > MaxSum)	/*如果刚得到的子列和更大,则更新结果*/ 
				MaxSum = ThisSum;
		}/*j循环结束*/ 
	}/*i循环结束*/ 
	return MaxSum;
 } 

算法2

  • 算法复杂度—— T ( N ) = O ( N 2 ) T(N)=O(N^2) T(N)=O(N2)
int MaxSubSum1(int A[], int N);
{
	int ThisSum, MaxSum = 0;		
	int i, j, k;					
	for( i = 0; i< N; i++)			/*i是子列左端位置*/ 
	{
		ThisSum = 0; 				/*ThisSum是A[i]到A[j]的子列和*/ 
		for( j = i; j < N; j++)		/*j是子列右端位置*/ 
		{
			ThisSum += A[j];		
			/*对于相同的i,不同的j,只要在j-1次循环的基础上累加1项即可*/ 
			if( ThisSum > MaxSum)	/*如果刚得到的子列和更大,则更新结果*/ 
				MaxSum = ThisSum;
		}/*j循环结束*/ 
	}/*i循环结束*/ 
	return MaxSum;
}	

算法3

  • 分而治之
  • 算法复杂度—— T ( N ) = O ( N l o g N ) T(N)=O(NlogN) T(N)=O(NlogN)

在这里插入图片描述

int Max3( int A, int B, int C )
{ /* 返回3个整数中的最大值 */
    return A > B ? A > C ? A : C : B > C ? B : C;
}

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 );
} 

算法4

  • 在线处理
  • 算法复杂度—— T ( N ) = O ( N ) T(N)=O(N) T(N)=O(N)
int MaxSubseqSum4(int A[], int N)
{
	int MaxSum, ThisSum;
	int i;
	ThisSum = MaxSum = 0;
	for(i=0; i<N; i++)
	{	ThisSum += A[i];		/*向右累加*/ 
		if( ThisSum > MaxSum)
			MaxSum = ThisSum;	/*发现更大和则更新当前结果*/ 
		else if( ThisSum < 0)	/*如果当前子列和为负,则不可能使后面的部分和更大,抛弃之*/ 
			ThisSum = 0;
	}
	return MaxSum; 
 } 
  • “在线”的意思是指每输入一个数据就进行即时处理,在任何一个地方终止输入,算法都能正确给出当前的解
  • 运行时间

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2021 Nqq

你的鼓励是我学习的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值