問題描述:
一個數組有N個元素,求這個數組中子數組的最大和。
要求:
- 子數組是數組中連續的幾個元素
- 數組的元素包含正數,負數,0
思路:
使用動態規劃的方式從第n-1個元素開始,向前累加。
如果當前值 大於當前值+以前和則在當前和的位置保存當前值,否則保存當前值+以前和
sum[n-2] = max(a[n-2], sum[n-1]+a[n-1]),
程序示例 : getMaxSum()
擴展問題:
如果數組首尾相鄰,找到其中一段最大和。
思路:
問題大概存在三種情況
第一種情況就是普通問題的解,
第二種和第三種是有循環的情形,從頭向尾循環和從尾向頭循環。
考慮先取得沒有循環時的一個最大值,再取得有循環時的最大值,再取他們中的最大值。
在計算循環的情況時,先找方向,確定是情況2,還是情況3。
再按照方向計算出一個循環情況下的最大值。
程序示例 : getMaxSumLoop()
#include <iostream>
using namespace std;
int max(int x, int y)
{
return (x > y) ? x : y;
}
int getMaxSum(int arr[], int len)
{
int i = 0, ret = 0, pos_s = 0, pos_e = 0;
int* start = NULL;
int* sum_max = NULL;
if (len == 0)
return 0;
start = new int[len];
sum_max = new int[len];
start[len-1] = arr[len-1];
sum_max[len-1] = arr[len-1];
pos_s = pos_e = len-1;
for (i = len-2; i>=0; i--)
{
start[i] = max(arr[i], arr[i] + start[i+1]);
sum_max[i] = max(start[i], sum_max[i+1]);
if (sum_max[i] == start[i])
{
if (start[i] == arr[i])
{
pos_s = i; pos_e = i;
}
else
{
pos_s = i;
}
}
}
ret = sum_max[0];
delete[] start;
delete[] sum_max;
cout << "Max= " << ret << " Start Pos = " << pos_s << " End Pos = " << pos_e << endl;
return ret;
}
int getMaxSumLoop(int arr[], int len)
{
int i = 0, ret = 0, pos_0 = 0, pos_last = 0;
int max_0 = 0, max_last = 0, sum_0 = 0, sum_last = 0;
int M1 = 0, M2 = 0;
if (len == 0)
return 0;
M1 = getMaxSum(arr, len);
max_0 = arr[0];
sum_0 = arr[0];
max_last = arr[len-1];
sum_last = arr[len-1];
for (i = 1; i < len; i++)
{
sum_0 += arr[i];
sum_last += arr[len-1-i];
if (sum_0 >= max_0)
{
max_0 = sum_0;
pos_0 = i;
}
if (sum_last >= max_last)
{
max_last = sum_last;
pos_last = len-1-i;
}
}
if (pos_0 >= pos_last)
{
if (max_0 > max_last)
{
M2 = max_0;
sum_0 = max_0;
for (i = len-1; i > pos_0; i--)
{
sum_0 += arr[i];
if (sum_0 >= M2)
{
M2 = sum_0;
}
}
}
else
{
M2 = max_last;
sum_last = max_last;
for (i = 0; i < pos_last; i++)
{
sum_last += arr[i];
if (sum_last >= M2)
{
M2 = sum_last;
}
}
}
}
else
{
M2 = max_0 + max_last;
}
if (M1>M2)
cout << "Max= " << M1 << endl;
else
cout << "Max (loop)= " << M2 << endl;
ret = max(M1, M2);
return ret;
}
void main()
{
int test1[] = {1,-2,3,5,-3,2};
int test2[] = {1,-2,3,5,-1,2};
int test3[] = {-9,-2,-3,-5,-3};
int len1 = sizeof(test1)/sizeof(test1[0]);
int len2 = sizeof(test2)/sizeof(test2[0]);
int len3 = sizeof(test3)/sizeof(test3[0]);
getMaxSum(test1, len1);
getMaxSum(test2, len2);
getMaxSum(test3, len3);
cout << "===============================" << endl;
getMaxSumLoop(test1, len1);
getMaxSumLoop(test2, len2);
getMaxSumLoop(test3, len3);
cin>> len1;
}