您的位置:首页 > 理论基础 > 数据结构算法

<数据结构与算法分析 C++描述>算法分析之最大子序列和问题

2015-01-24 13:51 806 查看
声明:这个系列博客是《数据结构与算法分析 C++描述》的读书笔记系列

参考博客:点击打开链接

本文是原书第二章内容,主要内容包括:算法的时间复杂度分析/算法的优化,分析的例子是很出名的最大子序列求和问题。

分为了四种方法来求解:穷举/穷举优化/递归(分治)/联机算法(动态规划), 算法复杂度为O(N^3)/O(N^2)/O(N*logN)/O(N). 思路都在具体代码里

----------------------------------------代码如下-------------------------------------------------------------------

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
/*
 *计算并返回最大子序列和:穷举遍历
 *算法复杂度:O(N^3)
 */
int maxSubSum1(const vector<int> & a)
{
	int maxSum=0;
	for(int i=0; i < a.size(); i++) {
		for(int j=i; j < a.size(); j++) {
			int thisSum = 0;
			for(int k=i; k <= j; k++)
				thisSum += a[k];
			if(thisSum > maxSum)
				maxSum = thisSum;
		}
	}
	return maxSum;
}
/*
 * 同样是穷举,对上面的穷举进行了优化
 * 算法复杂度:O(N^2)
 */
int maxSubSum2(const vector<int> &a)
{
	int maxSum = 0;
	for(int i = 0; i < a.size(); i++) {
		int thisSum = 0;
		for(int j=i; j < a.size(); j++) {
			thisSum += a[j];
			if(thisSum > maxSum)
				maxSum = thisSum;
		}
	}
	return maxSum;
}

/*
 *使用递归的思路,将序列分为左右以及中间三大部分,其中左右部分可以用递归解决,
 *而中间部分是前半部分(包含左半部分最后一个元素)的最大值和右半部分(包含右半部分的第一个值)的最大值的和
 *将这三个值做比较就是最终的结果
 *算法复杂度:O(N*logN)
 */
int maxSubSum3(const vector<int> &a, int left, int right)
{
	if( left == right) {
		if( a[left] > 0)
			return a[left];
		else
			return 0;
	}

	int center = (left + right)/2;
	int maxLeftSum = maxSubSum3(a, left, center);
	int maxRightSum = maxSubSum3(a, center+1, right);
	int maxLeftAndRight = max(maxLeftSum, maxRightSum);

	int maxLeftBorderSum = 0, leftBorderSum = 0;
	for(int i = center; i >= left; i--) {
		leftBorderSum += a[i];
		if( leftBorderSum > maxLeftBorderSum)
			maxLeftBorderSum = leftBorderSum;
	}

	int maxRightBorderSum = 0, rightBorderSum = 0;
	for(int i = center+1; i <= right; i++) {
		rightBorderSum += a[i];
		if( rightBorderSum > maxRightBorderSum)
			maxRightBorderSum = rightBorderSum;
	}

	return max(maxLeftAndRight, maxLeftBorderSum + maxRightBorderSum);
}
/*
 * 动态规划,联机算法(on-line algorithm)
 * 联机算法:在任意时刻,算法对要操作的数据只读入(扫描)一次,一旦被读入并处理,它就不需要在被记忆了。而在此处理过程中算法能对它已经读入的数据立即给出相应子序列问题的正确答案。具有这种特性的算法叫做联机算法(on-line algorithm)。
 * 算法复杂度:O(N)
 */
int maxSubSum4(const vector<int> &a)
{
	int maxSum=0;
	int thisSum=0;
	for(int i=0; i<a.size(); i++) {
		thisSum += a[i];
		if(thisSum > maxSum)
			maxSum = thisSum;
		else if(thisSum < 0)
			thisSum = 0;
	}
	return maxSum;
}

int main()
{
	int input[] = {4,-3,5,-2,-1,2,6,-2};
	int length = sizeof(input)/4;
	//注意这里用数组去给vector容器初始化赋值的时候,区间是[begin,end)
	vector<int> inputVector(&input[0], &input[length]);

	//int result = maxSubSum3(inputVector, 0 , inputVector.size()-1);
	int result = maxSubSum4(inputVector);
	cout << "the maxSubSum is " << result << endl;
	return 0;
}

//test
//input[8] = {4,-3,5,-2,-1,2,6,-2};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: