求数组最大连续元素之和

/*
DJ.W 2012.12.27
		代码功能: 
		输入: 一个整型数组
		输出: 该数组能得到的最大连续元素和
		如对输入 1 -2 -4 7 -6 9 最大连续元素和为10 (7 + (-6) + 9)
  问题以及算法思想来自《编程珠玑(第二版)》P77
 */

#include <iostream>
using namespace std;

#define max(a, b) (a>b? a:b)


/*二分思想
	思路,将数组从中间分为三个部分,左半部分,右半部分,和交界部分
	数组中最大连续元素和必定是三者其一,也就是最大的那一个。
	对于左右半部分,可以直接递归,中间部分就直接从中间开始向两边扩散。
	复杂度为O(n) 整个算法复杂度为O(nlgn)
	这个解法需要认真想想它是怎样保证得到的和一定是连续元素块的。
*/
int maxsum(int* p, int start, int end)
{
	//终止条件 递归到长度为1的子数组,这个时候
	//自然是该数是正就加上是负则舍去(返回0)
	if(start == end)
	{
		if(p[start] > 0)
			return p[start];
		else
			return 0;
	}

	//找到中点
	int mid = (start+end)/2;

	//从中点向左扩展 找到向左能得到的最大和
	int sum_mid = 0;
	int temp = 0;
	for (int i= mid; i>=start; i--)
	{
		temp = temp+p[i];
		if (temp > sum_mid)
			sum_mid = temp;
	}

	temp = sum_mid;

	//从中点向右扩展 找到向右扩展能得到的最大和
	for (i = mid+1; i<=end; i++)
	{
		temp = temp+p[i];
		if (temp > sum_mid)
			sum_mid = temp;

	}

	//递归左右两半部分 得到三个部分中最大和
	return max(max(maxsum(p, start, mid), maxsum(p, mid+1, end)), sum_mid);
}

/*扫描法
	算法思想:
	从左到右扫描数组A,当扫描到i时,设立两个变量sumCur和maxSofar
	sumCur为当前扫描到的下标i之前得到的累加值。maxSofar是当前得到
	过的最大元素和。如果sumCur = sum(A[0]...A[i])<=0
	那么可以判定A[0...i]必定不会在最终得到的最大连续元素和的
	序列中(这里假设我们力求得到的连续元素个数最少,因此加上了=)。
	因此我们重设sumCur=0(相当于舍弃了A[0...i])
	如果sumCur > 0 则继续扫描A[i+1] 此时如果A[i+1]>=0 那么
	maxSofar = sumCur+A[i+1] 否则maxSofar不变。当扫描完数组后
	maxSofar即为所求
*/
int maxsum_scan(int* arr, int size)
{
	int sumCur = 0;
	int maxSofar = 0;
	for (int i=0; i<size; i++)
	{
		sumCur = max(sumCur+arr[i], 0);
		maxSofar = max(maxSofar, sumCur);
	}
	return maxSofar;
}
int main()
{
	int test[10] = {10, -9, 6, 33, -12, 5, 19, 8, 13, -2};
	
	//int sum = maxsum(test, 0, 9);
	int sum = maxsum_scan(test, 9);
	cout<<"Test Sum = "<<sum<<endl;

	return 0;
}

你可能感兴趣的:(求数组最大连续元素之和)