算法导论之寻找最大子数组

bool FindMaxmumSubArray(float A[], int low, int high, float &fMaxmumSum, int &iFrom, int &iTo)
{
	// 判断输入条件
	if (low < 0 || high < 0 || low > high)
	{
		return false;
	}
	
	if (low == high)
	{
		iFrom = iTo = low;
		return true;
	}
	
	// 分段;
	int iMid = (low + high) / 2;
	
	// 最大子数组要么在left ~ mid, 或 mid + 1 ~ right, 或横跨mid的 left-right 区间;
	int iLeftFrom = 0;
	int iLeftTo = 0;
	float fLeftSum = 0.0;
	// 寻找左边数组
	bool bLeftRes = FindMaxmumSubArray(A, low, iMid, fLeftSum, iLeftFrom, iLeftTo);
	if (!bLeftRes)
	{
		return false;
	}
	
	int iRightFrom = 0;
	int iRightTo = 0;
	float fRightSum = 0.0;
	// 寻找右边数组
	bool bRightRes = FindMaxmumSubArray(A, iMid + 1, high, fRightSum, iRightFrom, iRightTo);
	if (!bRightRes)
	{
		return false;
	}
	
	int iCrossingFrom = 0;
	int iCrossingTo = 0;
	// 寻找横跨mid 的子数组;
	float fCrossingSum = 0.0;
	bool bCrossingRes = FindMaxmumCrossingSubArray(A, low, mid, high, fCrossingSum, iCrossingFrom, iCrossingTo);
	if (!bCrossingRes)
	{
		return false;
	}
	
	// 如果左边的子数组和最大
	if (fLeftSum >= fRightSum && fLeftSum >= fCrossingSum)
	{
		iFrom = iLeftFrom;
		iTo = iLeftTo;
		fMaxmumSum = fLeftSum;
	} // 如果右边的子数组和最大
	else if (fRightSum >= fLeftSum && fRightSum >= fCrossingSum)
	{
		iFrom = iRightFrom;
		iTo = iRightTo;
		fMaxmumSum = fRightSum;
	}
	else // 最后必定是中间子数组最大;
	{
		iFrom = iCrossingFrom;
		iTo = iCrossingTo;
		fMaxmumSum = fCrossingSum;
	}
	
	return true;
}

// 寻找横跨mid的最大子数组;
bool FindMaxmumCrossingSubArray(float A[], int low, int mid, int high, float &fCrossingSum, int &iFrom, int &iTo)
{
	if (low < 0 || high < 0 || low > high)
	{
		return false;
	}
	
	float fCurrentSum = 0.0;
	// 从mid 开始求取左边最大和
	float fLeftMaxmumSum = -1e7;
	for (int i=mid; i>=low; i--)
	{
		fCurrentSum += A[i];
		if (fCurrentSum > fLeftMaxmumSum)
		{
			fLeftMaxmumSum = fCurrentSum;
			iFrom = i;
		}
	}
	
	// 从mid 开始求取右边最大和
	fCurrentSum = 0.0;
	float fRightMaxmumSum = 1e-7;
	for (int i=mid+1; i<=high; i++)
	{
		fCurrentSum += A[i];
		if (fCurrentSum > fRightMaxmumSum)
		{
			fRightMaxmumSum = fCurrentSum;
			iTo = i;
		}
	}
	
	// 最大子数组的和;
	fCrossingSum = fLeftMaxmumSum + fRightMaxmumSum;
	
	return true;
}


// by 我执可破. 2016.11.10 于上海浦东;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值