面试题(十)连续子数组的最大和、最大差

这个题目是个很常见的面试题,主要的解法之一是DP方法,也是最简单的方法

这个问题的DP解答核心在于维护一个END[i],END[i]代表以pArray[i]为结尾的子数组的最大和。

已经假定了pArray[i]是这个子数组的最后一个数字,那么END[i-1]+Parray[i]<=END[i],当END[i-1]大于等于0时,等号成立,这是整个解法的思想

代码如下

int getMaxSum(int *pArray,int nSize)
{
	if (pArray==NULL)
	{
		return -1;
	}
	int	nSum=0;
	int nMaxSum=-INF;
	
	for (int i=0;i<nSize;i++)
	{
		if (nSum<0)
		{
			nSum=pArray[i];
		}
		else
		{
			nSum+=pArray[i];
		}
		if (nSum>nMaxSum)
		{
			nMaxSum=nSum;
		}
	}
	return nMaxSum;
}
关于最大差,有道google面试题:

给定一个数组,我们可以找到两个不相交的,并且是连续的子数组A和B,A中的数字和为sum(A),B中的数字和为sum(B),找到这样的A和B,满足Sum(A)-sum(B)的绝对值是最大的。

例如:[2 -1 -2 1 -4 2 8]划分为A=[-1 -2 1 -4] B=[2,8] 最大值为16。
可以使用基于划分的方法,求的这个划分点左边数组的最大和,右边数组的最小和,或者相反,最后求差,最后遍历整个划分策略

代码如下

int getMaxDiff(int *pArray,int nSize)
{
	if (pArray==NULL)
	{
		return -INF;
	}
	int *pEndMax=new int[nSize];//从左往右
	int *pEndMin=new int[nSize];//从左往右
	int *pStartMax=new int[nSize];//从右往左
	int *pStartMin=new int[nSize];//从右往左
	
	pEndMin[0]=pArray[0];
	pEndMax[0]=pArray[0];
	for (int i=1;i<nSize;i++)
	{
		if (pEndMax[i-1]<=0)
		{
			pEndMax[i]=pArray[i];
		}
		else
		{
			pEndMax[i]=pEndMax[i-1]+pArray[i];
		}
		if (pEndMin[i-1]<=0)
		{
			pEndMin[i]=pEndMin[i-1]+pArray[i];
		}
		else
		{
			pEndMin[i]=pArray[i];
		}
	}

	pStartMin[nSize-1]=pArray[nSize-1];
	pStartMax[nSize-1]=pArray[nSize-1];
	
	for (int i=nSize-2;i>=0;--i)
	{
		if (pStartMax[i+1]>=0)
		{
			pStartMax[i]=pStartMax[i+1]+pArray[i];
		}
		else
			pStartMax[i]=pArray[i];
		if (pStartMin[i+1]<0)
		{
			pStartMin[i]=pStartMin[i+1]+pArray[i];
		}
		else
			pStartMin[i]=pArray[i];
	}

	int nMaxdiff=pEndMax[0]-pStartMin[1];

	for (int partitionIndex=0;partitionIndex<nSize-1;partitionIndex++)
	{
		int diff=abs(pEndMax[partitionIndex]-pStartMin[partitionIndex+1]);
		if (diff>nMaxdiff)
		{
			nMaxdiff=diff;
		}
		diff=abs(pEndMin[partitionIndex]-pStartMax[partitionIndex+1]);
		if (diff>nMaxdiff)
		{
			nMaxdiff=diff;
		}
	}

	delete []pEndMax;
	delete []pEndMin;
	delete []pStartMax;
	delete []pStartMin;


	return nMaxdiff;		
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值