最大子序列和问题

算法1:
对于第一种算法比较直接,就是从头到尾计算一遍,然后计算最大值就可以了。时间复杂度为O(n^3).

#include<stdio.h>
int Maxsum(int a[],int n)
{
	int sum,maxsum=0;
	//i和j分别是子序列的左端和右端 
	//遍历i,j的所有情况 
	for(int i=0;i<n;i++)
	{
		for(int j=i;j<n;j++)
		{
			sum=0;
			//求子序列和 
			for(int k=i;k<=j;k++)
			{
				sum+=a[k];
				if(sum>maxsum)
				maxsum=sum; 
			}
		}
	}
	return maxsum;
}
int main()
{
	int a[10]={4,-3,5,-2,-1,2,6,-2};
	printf("%d\n",Maxsum(a,8));
}
 

算法2:基于第一种方法的改进。算法一中求子序列和是通过从i到j挨个累加的方式,因为求下个子序列和时又得从i开始,造成很多重复,所以算法2中是通过在之前所求子列和的基础上再加1个元素的方式,时间复杂度为O(n^2).

#include<stdio.h>
int Maxsum2(int a[],int n)
{
	int sum,maxsum=0;
	//i和j分别是子序列的左端和右端 
	for(int i=0;i<n;i++)
	{
		sum=0;
		for(int j=i;j<n;j++)
		{
			sum+=a[j];//子序列和为之前子序列加1个数后的值 
			if(sum>maxsum)
			maxsum=sum; 
		}
	}
	return maxsum;
}
int main()
{
	int a[10]={4,-3,5,-2,-1,2,6,-2};
	printf("%d\n",Maxsum2(a,8));
}



算法3:分而治之。
思想是将数列在中间一分为二,则最大子序列和只有3种可能:
1.在左子序列
2.在右子序列
3.跨中间分割线的子序列
通过递归就可以求得最大子序列。时间复杂度为O(nlogn).

#include<stdio.h>
#define max(m,n) (m)>(n)?(m):(n) 
int Maxsum3(int a[],int i,int j)
{
	int begin=i,end=j,max; //序列的开始和结尾
	int mid=(begin+end)/2;
	int maxr,maxl,maxn;
	int rBorderSum=0,lBorderSum=0;
	int maxrBorderSum=0,maxlBorderSum=0;
	if(i==j)
	{
		if(a[i]>0)
		return a[i];
		else 
		return 0;
	}
	else
	{
		maxl=Maxsum3(a,begin,mid);
		maxr=Maxsum3(a,mid+1,end);
		for(int k=mid;k>=begin;k--)
		{
			lBorderSum+=a[k];
			if(lBorderSum>maxlBorderSum)
			maxlBorderSum=lBorderSum;
		}
		for(int k=mid+1;k<=end;k++)
		{
			rBorderSum+=a[k];
			if(rBorderSum>maxrBorderSum)
			maxrBorderSum=rBorderSum;
		}
		maxn=maxlBorderSum+maxrBorderSum;	
		return max(max(maxl,maxr),maxn);	
	 } 
}
int main()
{
	int a[10]={4,-3,5,-2,-1,2,6,-2};
	printf("%d\n",Maxsum3(a,0,7));
}
 
算法4:在线处理法
也就是边扫描边处理,如果当前扫描子序列和大于原最大子序列和就更新最大子序列和;如果当前子序列和为负数则,舍弃该子序列。

#include<stdio.h>
#define max(m,n) (m)>(n)?(m):(n) 
int Maxsum4(int a[],int n)
{
	int ThisSum,MaxSum;
	ThisSum=MaxSum=0;
	for(int i=0;i<n;i++){
		//向右累加 
		ThisSum+=a[i];
		if(ThisSum>MaxSum)
		MaxSum=ThisSum;//发现更大的就更新当前结果
		else if(ThisSum<0)
		ThisSum=0;//如果当前子序列和为负数,则抛弃之 
	}
	return MaxSum; 
}
int main()
{
	int a[10]={4,-3,5,-2,-1,2,6,-2};
	printf("%d\n",Maxsum4(a,8));
}






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值