连续子数组最大和问题(能够处理全是负数,返回子数组的起止索引的O(N)算法)

问题描述:给定长度为n的整数序列,a[1...n], 求[1,n]某个子区间[i , j]使得a[i]+…+a[j]和最大.或者求出最大的这个和.例如(-2,11,-4,13,-5,2)的最大子段和为20,所求子区间为[2,4].

求子区间及其最大值,是非常适合采用分治法德算法设计思想来设计的,其分治的思想是把一个难以直接解决的大问题,分成一些规模较小的相同性质的问题,以便各个击破,分而治之。如果规模为N的问题可以分解成k个子问题(1<k<=N),并且这些子问题之间相互独立,互不影响,递归地解决这些问题,然后合并这些子问题的解,得到最后问题的解。

分治法的代码实现过程如下:

int MaxSubSum(int a[],int left,int right)
{
	int sum = 0;		//用来存储最大子段和
	if (left == right)	//只有一个元素
	{
		sum = a[left] > 0 ? a[left] : 0;
	}
	else
	{
		int center = (left + right)/2;
		int leftsum = MaxSubSum(a,left,center);
		int rightsum = MaxSubSum(a,center+1,right);

		//下面是第三种情况
		int s1 = 0,lefts = 0;
		for (int i = center; i >= left; i --)
		{
			lefts += a[i];
			if (lefts > s1)
				s1 = lefts;
		}

		int s2 = 0,rights = 0;
		for (i = center+1; i <= right; i ++)
		{
			rights += a[i];
			if (rights > s2)
				s2 = rights;
		}

		sum = s1 + s2;
		if (sum < leftsum)
			sum = leftsum;
		if (sum < rightsum)
			sum = rightsum;
	}
	return sum;
}




这个函数的时间复杂度是O(n*log n) ,那能不能找到一个O(N)时间复杂度,O(1)空间复杂度的算法呢?并且加大问题的难度,能够返回子数组的开始和结束的索引,并且能够处理数组全是负数的情况,当全是负数时,返回最大的那么元素值作为最大值,并且找到这个数所在的索引?答案是肯定的,在这里就要借助于动态规划算法来解决。

其基本思路如下:

用b记录当前的最大值

nMax记录最大值,即返回值

1、如果b>0,则b+a[i];如果b<=0,则b=a[i]

2、若b>nMax,则nMax=b,即更新最大值,否则最大值不更新


//标示输入数据是否有效
static bool bInvalidInput = false; 

int MaxSubSum3(int *a, int nCount,int &nStart,int &nEnd)
{
	if (a == NULL || nCount <= 0)
	{
		bInvalidInput = true;
		return -1;
	}

	//初始化前后的索引
	nStart = 0;
	nEnd = 0;
	if (1 == nCount)
	{
		return a[0];
	}
	
	int nSubMax = a[0];		//当前最大值
	int nMax = nSubMax;			//子数组之和最大值

	for (int i = 1; i < nCount; i ++)
	{
		if (nSubMax > 0)
		{
			nSubMax += a[i];

		}

		else if (nSubMax <= 0)
		{
			if (a[i] > nSubMax)
			{
				nSubMax = a[i];
				nStart ++;
			}
			
		}

		//更新最大值
		if (nSubMax > nMax)
		{
			nMax = nSubMax;
			nEnd = i;
		}
	}

	return nMax;

}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值