3.求子数组的最大和

3.求子数组的最大和
题目:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为O(n)。
例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,
因此输出为该子数组的和18。

//July 2010/10/18

还有全是负数时。


错误的方法及分析:a[MAX]={1, -2, 3, 10, -4, 7, 2, -5}; 

dp[0]=a[0];
for (i=1; i<8; i++)

dp[i]=max(dp[i-1],(dp[i-1]+a[i]));是错误的,这里面当遇到负数时,会跳过,不计算,则不是连续的子数组。

这个结果是错误的,结果如下:

dp[i]=max{dp[i-1],dp[i-1]+a[i]}
 01234567
a1-2310-472-5
dp1141414212323

正确的方法及分析:

其中,start[1]为包含A[1]的和的最大一段数组,则start[0]为包含A[0]的和的最大一段数组,而All[1]为A[1]-------A[n-1]中和的最大的一段数组,则All[0]为A[0]-------A[n-1]中和的最大的一段数组。

而All[0]=max{start[0],All[1]},且start[0]=max{A[0],A[0]+start[1]}。

故可知All[i]=max{start[i],All[i+1]},且start[i]=max{A[i],A[i]+start[i+1]}。

由start[i]=max{A[i],A[i]+start[i+1]}可知,start[i]需要由start[i+1]求出,故此例为从右到左计算;其中当start[i+1]<0时,start[i]=A[i],start[i+1]为从A[i+1]开始并包含A[i+1]的和的最大一段数组,我们可以用sum来表示,这样,只需o(1)的空间即可,而不是o(n)的空间;当start[i+1]<0时,即从A[i+1]开始且包含A[i+1]的最大和小于0,即sum<0时,sum=A[i];用max来表示All之后由后向前开始计算。

程序如下:

int Max(int x,int y)
{
	return x>y?x:y;
}
int MaxSum(int *A,int n)
{
	sum=A[n-1];
	max=A[n-1];
	for (i=n-2; i>=0; i--)
	{
		sum=Max(A[i],sum+A[i]);
		max=Max(sum,max);
	}
}

上式也可以换个写法,同样从右向左,

int Maxsum(int *A,int n)
{
	sum=A[n-1];
	max=A[n-1];
	for (i=n-2; i>=0; i--)
	{
		if (sum<0)
		{
			sum=A[i];
		}
		else
		{
			sum+=A[i];
		}
		/*或者if...else...写成下面这样 
		if(sum<0)
		{
			sum=0;
		}
		sum+=A[i];
		*/
		if (sum>max) 
		{
			max=sum;
		}
	}
	return max;
} 

当然,也可以从左到右计算,图例如下:


All[n-1]=max{All[n-2],end[n-1]},end[n-1]=max{end[n-2]+A[n-1],A[n-1]},

由此推出:All[i]=max{All[i-1],end[i]},end[i]=max{end[i-1]+A[n-1],A[n-1]}。

包含A[i]的累加和最大用sum表示,当sum<0时,sum=A[i+1],在和max比较。

sum、max、start、end
 01234567
 1-2310-472-5
sum1-13139161813
max1131313161818
start00222222
end00233566
当sum<0之后,start开始变化,当sum>max时,end开始变化,而当全是负数时,start>end,故将start更新为end。

正确代码如下:从左向后

#include<stdio.h>
#include<stdlib.h>
#define MAX 100
int main()
{
	int i,max,sum,start,end;
	int a[MAX]={-11, -2, -3, -10, -4, -7, -2, -5}; 
	max=a[0]; sum=a[0]; start=0; end=0;
	for (i=1; i<8; i++)
	{
		if (sum<0)
		{
			sum=a[i];
			start=i;
		}
		else 
		{
			sum+=a[i];
		}
		if (sum>max)
		{
			max=sum;
			end=i;
		}
	}
	printf("max=%d\n",max);
	if (start>end) 
	{
		start=end;
	}
	printf("start=%d end=%d\n",start,end);
	system("pause");
}
max=-2
start=1 end=1

如:a[MAX]={1, -2, 3, 10, -4, 7, 2, -5}; 

则max=18
start=2 end=6

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值