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

题目

一个有N个整数元素的一维数组,{A[0]…A[n-1]},求该数组所有子数组中的最大和。 题意明确:

  1. 题目中说的子数组是连续的;
  2. 题目只需要求和,并不需要返回子数组的具体位置;
  3. 数组的元素是整数,所以数组可能包含有正整数,零和负整数;

例: 数组[ 1,-2,3,5,-3,2 ]返回8;

分析

《编程之美》P183-188中详细讲述了,该题目从最初暴力O(n^3)的解法,优化到最后O(N)的步骤;

代码

/*
2.14 求数组的子数组之和的最大值
*/

#include <iostream>
#include <cstdlib>
#include <vector>
#include <algorithm>

using namespace std;

/*方法一:罗列所有的子数组,求每个子数组的和,时间复杂度O(n^3)*/
int maxSubSum(const vector<int> &nums)
{
	if (nums.empty())
	{
		return 0;
	}//if

	int len = nums.size();

	int maxSum = INT_MIN, tmpSum = 0;
	for (int i = 0; i < len; ++i)
	{
		for (int j = i; j < len; ++j)
		{
			/*清0临时子数组的和*/
			tmpSum = 0;
			/*求i到j的子数组之和*/
			for (int k = i; k <= j; ++k)
			{
				tmpSum += nums[k];
			}//for

			if (tmpSum > maxSum)
			{
				maxSum = tmpSum;
			}//if
		}//for
	}//for

	return maxSum;
}

/*方法二:注意到sum[i...j] = sum[i-1 ... j] + nums[j] , 复杂度降低到O(n^2)*/
int maxSubSum2(const vector<int> &nums)
{
	if (nums.empty())
	{
		return 0;
	}//if

	int len = nums.size();

	int maxSum = INT_MIN, tmpSum = 0;
	for (int i = 0; i < len; ++i)
	{
		tmpSum = 0;
		for (int j = i; j < len; ++j)
		{
			tmpSum += nums[j];

			/*从i到j的子数组之和为tmpSum*/
			if (tmpSum > maxSum)
				maxSum = tmpSum;
		}//for
	}//for
	return maxSum;
}

/*方法三:分治法的思想,分为规模减半的子问题,通过递归解决;复杂度O(nlogn)*/


/*方法四:动态规划max{A[0], A[0]+start[1], ALL[1]},时间复杂度O(N),空间复杂度O(N)*/
int maxSubSum4(const vector<int> &A)
{
	if (A.empty())
	{
		return 0;
	}//if

	int len = A.size();
	/*Start数组中存放的是,以下标i对应元素为起始点的最大子数组之和*/
	vector<int> Start(len, 0);
	/*All数组中存放的是,从下标[i...len-1]实际最大子数组之和*/
	vector<int> All(len, 0);
	
	/*从数组末尾向前遍历,知道数组首部*/
	Start[len - 1] = A[len - 1];
	All[len - 1] = A[len - 1];

	for (int i = len - 2; i >= 0; --i)
	{
		Start[i] = max(A[i], A[i] + Start[i + 1]);
		All [i] = max(Start[i], All[i + 1]);
	}//for
	return All[0];	
}

/*方法五:四的改进,空间复杂度减低到O(1)*/
int maxSubSum5(const vector<int> &A)
{
	if (A.empty())
	{
		return 0;
	}//if

	int len = A.size();
	int nStart = A[len - 1], nAll = A[len - 1];

	for (int i = len - 2; i >= 0; --i)
	{
		nStart = max(A[i], nStart + A[i]);
		nAll = max(nStart, nAll);
	}//for
	return nAll;
}

/*方法六:线性时间复杂度*/
int maxSubSum6(const vector<int> &A)
{
	if (A.empty())
	{
		return 0;
	}//if
	/*求数组A的长度*/
	int n = A.size();
	int maxSum = A[n - 1], tmpSum = A[n - 1];
	for (int i = n - 2; i >= 0; --i)
	{
		if (tmpSum < 0)
		{
			tmpSum = 0;
		}//if

		tmpSum += A[i];
		if (tmpSum > maxSum)
			maxSum = tmpSum;
	}//for
	return maxSum;
}

int main()
{
	vector<int> A = { 1,-2,3,5,-3,2 };
	cout << maxSubSum(A) << endl;
	cout << maxSubSum2(A) << endl;
	cout << maxSubSum4(A) << endl;
	cout << maxSubSum5(A) << endl;
	cout << maxSubSum6(A) << endl;

	system("pause");
	return 0;
}

    原文作者:逆風的薔薇
    原文地址: https://blog.csdn.net/fly_yr/article/details/51464477
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞