问题描述:
一个数组有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;
}