首页 > 代码库 > 编程之美2.14 求数组的子数组之和的最大值

编程之美2.14 求数组的子数组之和的最大值

      这是一个在面试中出现概率很高的一道题目,就拿我来说吧,面试了5家公司中,两家公司问了这道题目,可见,这道题目是非常经典的。

      解题思想也不是很难,我熟悉的有;两种解题办法:

      1. 一直连加,终止当前序列的条件是连加的和是负数

      因为,一个数加上一个负数之后肯定是没有原来的数值大,所以,这肯定是没有意义的,最终,我们利用这个思想得到如下的解法。

      函数声明:

ll DutMaxSeqSubArray_1(int*, int);

typedef long long ll;

      源代码:

/*非常常见的最大连续子数组的解法*/
bool _DutMaxSeqSubArray = false;
ll DutMaxSeqSubArray_1(int* A, int size)
{
	if (!A || size <= 0)
	{
		_DutMaxSeqSubArray = true;

		return -1;
	}

	ll result = 1 << 31;
	ll currentSum = 0;

	/*循环走一遍数组,遇到加和为负数时就开始下一轮加和*/
	for (int i = 0; i < size; ++i)
	{
		if (currentSum <= 0)
			currentSum = A[i];
		else
			currentSum += A[i];

		if (result < currentSum)
			result = currentSum;
	}

	return result;
}

      2. 动态规划的思想:连续子数组最大和也一定是以某一个值结尾

      无论连续子数组有几个数,也不论和是多大,它总是以一个数结束的,而那个数肯定也是出现在数组中,所以,可以得到如下的递推公式: 

      以当前数结尾的最大连续子数组之和是:

      pData[i] = pData[i - 1] + A[i] || A[i]

      所以,可以得到如下的解法:

      函数声明:

ll DutMaxSeqSubArray_2(int*, int);

      源代码:

/*动态规划的解法*/
ll DutMaxSeqSubArray_2(int* A, int size)
{
	if (!A || size <= 0)
	{
		_DutMaxSeqSubArray = true;

		return -1;
	}

	ll result = 1 << 31;
	ll currentSum = 0;

	for (int i = 0; i < size; ++i)
	{
		/*
		 *思想是,最大连续子数组肯定是以某一个数组元素结尾的,所以,
		 *按照那个数字结尾时的最大加和就可以求得整个
		 *数组的最大连续之和
		 */
		currentSum = DutMax<ll>(currentSum + A[i], A[i]);
		result = DutMax<ll>(result, currentSum);
	}

	return result;
}

      用到的模板函数:

template <typename T>
T DutMax(T data1, T data2)
{
	return data1 > data2 ? data1 : data2;
}


编程之美2.14 求数组的子数组之和的最大值