现在的位置: 首页 > 综合 > 正文

一维子数组最大和

2019年10月16日 ⁄ 综合 ⁄ 共 1852字 ⁄ 字号 评论关闭
/*
 * MaxSumSubArray.cpp
 *
 *  Created on: 2012-6-20
 *      Author: jiyiqin
 *
 *  给定一个包含正数,负数,0的数组,求一个连续的子数组,使得其和最大
 */
#include <iostream>
using namespace std;

#define MIN_INT -10000
class MaxSumOfSubArray{
public:

	/**
	 * 二重循环查找最大和子数组,依次以a[i]为起点,
	 * 求解sum[i,j],更新当前最大和的值
	 * 注意数组全是负数的情况
	 * */
	static int m1_subArray(int a[], int size)
	{
		int max_sum = MIN_INT;					//max赋值一次
		if(a == NULL || size <=0) return -1;	//输入是否合法判断

		for(int i=0;i<size;i++)
		{
			int sum = 0;
			for(int j=i;j<size;j++){
				sum += a[j];
				if(sum > max_sum) max_sum = sum;	//更新max
			}
		}
		cout<<"max_sum:"<<max_sum<<endl;
		return 1;
	}

	/**
	 * 线性时间完成:
	 * 记录当前max,逐个累加
	 * 如果和sum变成负,丢弃(更新起点)。
	 * 如果sum > max,更新max。
	 * 注意数组全部是负数的时候,"负数和"也拥有和当前最大和比较的权利
	 * */
	static int m2_subArray(int a[], int size)
	{
		int max_sum = MIN_INT;					//最大和初值为最小数字
		int sum = 0;
		if(a == NULL || size <=0) return -1;	//输入是否合法判断

		for(int i=0;i<size;i++)
		{
			sum += a[i];
			if(sum > max_sum) max_sum = sum;	//更新max
			if(sum <= 0) sum = 0;				//重新开始计算和
		}
		cout<<"max_sum:"<<max_sum<<endl;
		return 1;
	}

	/**
	 * 动态规划方法:
	 * 很明显求解最大子数组和的问题有子结构,并且满足“无后效性”。
	 * 即问题可以被划分为多个阶段,未来阶段状态f(i+1)的求解仅仅与
	 * 当前状态f(i)通过状态转移方程得到,而与过去的历史状态无关。
	 * 我们设sum(i)为以a[i]结尾的最大子数组和.
	 *
	 * 如果sum(i-1) =< 0:
	 * 		很明显我们不应当将其简单抛弃,因为我们还要考虑数组a全部都是负数的情况,
	 * 		所以我们仍然将其与a[i]比较,所以sum(i) = max{sum(i-1), a[i]};
	 * 如果sum(i-1) > 0:
	 * 		因为sum(i-1)是以a[i-1]结尾的,所以很明显sum(i) = sum(i-1)+a[i];
	 * 所以我们得到状态转移方程如下:
	 * sum(i) =
	 * 		sum(i-1)+a[i];			sum(i-1) > 0
	 * 		max{sum(i-1), a[i]};	sum(i-1) <= 0
	 * */
	static int m3_subArray(int a[], int size)
	{
		int *sum = new int[size];
		int max_sum = MIN_INT;
	
		if(a == NULL || size <= 0) return -1;	//判断输入是否合法
		for(int k=0;k<size;k++) sum[k] = 0;		//初始化sum数组

		//顺着i自底向上求解
		sum[0] = a[0];
		for(int i=1;i<size;i++)
		{
			if(sum[i-1] > 0) sum[i] = sum[i-1]+a[i];
			else sum[i] = sum[i-1]>a[i]?sum[i-1]:a[i];
			
			//更新max_sum
			if(sum[i] > max_sum) max_sum = sum[i];
		}
		
		//输出结果
		cout<<"max_sum:"<<max_sum<<endl;
		for(int j=0;j<size;j++)
			cout<<sum[j]<<" ";
		cout<<endl;
		return 1;
	}

	static void test(){
		int a[10] = {-1,2,-5,2,-1,-13,15,-2,8,-1};
		for(int i=0;i<10;i++){
			cout<<a[i]<<" ";
		}
		cout<<endl;

		m1_subArray(a, 10);	//方法1
		m2_subArray(a, 10);	//方法2
		m3_subArray(a, 10);	//方法3
	}
};

int main(){
	MaxSumOfSubArray::test();
	return 0;
}

抱歉!评论已关闭.