最大子序列和

问题描述:

给定N个整数(有正有负),求它的最大子序列和,若全是负数则返回0。

例如:-84 33 -40 36 -34 4 5 88 74 -29

这10个数的最大子序列和是 173(74+88+4+5+(-34)+36)


解法:

1)穷举求解(三次循环,复杂度O(n^3))

for(i=0;i!=n;i++)/*对数组的元素全部遍历*/
{
 	for(j=i+1;j!=n;++j)/*从下一个位置开始遍历*/
 	{
 		sum=0; /*每次求上面两段位置和之前清0*/
 		for(k=i;k<=j;++k)/*求这两段位置的和*/
 		{
   			sum+=a[k];
   			if(sum>max)/*如果比最大值的话,记录下来*/
   			{
  				 max=sum;
   			}
 		}
	}
}

2)方法一的改进(二次循环,复杂度:O(n^2))

其实子序列的和我们并不需要每次都重新计算一遍。假设Sum(i, j)是A[i] ... A[j]的和,那么Sum(i, j+1) = Sum(i, j) + A[j+1]。利用这一个递推,我们就可以得到下面这个算法:

int MaxSequenceSum(int a[],int n)
{
 int ThisSum,MaxSum;            //ThisSum保存当前子序列和,MaxSum保存最大子序列和 
 int i,j;
 MaxSum = 0;
 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)线性算法

long int cSum = 0,MaxSum = 0;
		for(int i =0;i < n;i++)
		{
			scanf("%ld",&tmp);
			if(i == 0)
				MaxSum = tmp;//若不加这句,对于全是负数的情况输出的是0 
			cSum += tmp;
			if(cSum > MaxSum)
				MaxSum = cSum;
			if(cSum < 0)
				cSum = 0;
		}
		printf("%ld\n",MaxSum);

在这一遍扫描数组当中,从左到右记录当前子序列的和temp_sum,若这个和不断增加,那么最大子序列的和max也不断增加(不断更新max)。如果往前扫描中遇到负数,那么当前子序列的和将会减小。此时temp_sum 将会小于max,当然max也就不更新。如果temp_sum降到0时,说明前面已经扫描的那一段就可以抛弃了,这时将temp_sum置为0。然后, temp_sum将从后面开始将这个子段进行分析,若有比当前max大的子段,继续更新max。这样一趟扫描结果也就出来了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值