您的位置:首页 > 职场人生

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

2014-06-23 15:38 316 查看
这个题目是个很常见的面试题,主要的解法之一是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;
}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: