/*
* 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;
}