昨天偶然上csdn,看到这个问题,学习了一种复杂度为O(n)的算法,可以计算Array的最大子数组问题。思路就是从0-length,将array累加起来,同时用一个变量max记录最大值,如果sum > max,就更新max,如果sum < 0 就令sum = 0(为什么是这样呢,sum < 0的话,前面的就可以直接舍弃了)。附上代码:
#include <iostream>
using namespace std;
void MaxSubArray(int array[], int len) {
int sum = 0, max = array[0], s = 0, s_pos = 0, e_pos = 0;
for (int i = 0; i < len; i++) {
sum += array[i];
//sum > max 更新 max, 并把终点位置置为 i
if (sum > max) {
e_pos = i;
s_pos = s;
max = sum;
}
//sum < 0的话,就该把前面的抛弃,并且重置sum 为 0, 起始位置为 i + 1
if (sum < 0) {
sum = 0;
s = i + 1;
}
//sum > 0,继续 (假设最大子数组在中间 array[i~j]
//因为 array[k~i-1]的和大于0,则array[k~j]显然是更大的子数组) 因此 sum > 0时候,继续
}
cout << "start position: " << s_pos << endl;
cout << "end position: " << e_pos << endl;
cout << "max value: " << max << endl;
}
int main()
{
int A[] = { 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7};
MaxSubArray(A, sizeof(A)/sizeof(int));
system("pause");
return 0;
}
这个还记录了位置,真是短小而精悍的代码,我是看这里的评论的http://blog.youkuaiyun.com/xjm199/article/details/17954997#comments然后改了下代码而已
接着又看到一篇动态规划的最大子数组问题,http://blog.youkuaiyun.com/xjm199/article/details/17953753,看了下,觉得这跟上面的方法就是一样的,那个dp[i]也不是记录着dp[0~i]的最大子数组问题,于是我就想用dp[i]记录dp[0~i]的最大子数组问题值,用动态规划,就是考虑当前的array[i]是不是最大子数组的一员,如果是要怎么做,不是要怎么做,代码如下:
#include <iostream>
#define SIZE 9
using namespace std;
void MaxSubArray(int array[], int dp[], int len) {
dp[0] = array[0]; //只有一个元素时,dp[0]显然为array[0]
int end_position = 0; //记录最大子数组末尾点
for (int i = 1; i < len; i++) {
int max = array[i], sum = 0, sum2 = 0, j, s0 = i, st = i, en = i;
/*这个for循环是表示子数组要包括Array[i],则从i到end_position
看看此数组的中最大子数组和为多少*/
for (j = i; j > end_position; j--) {
sum += array[j];
sum2 += array[j];
if (sum > max) {
max = sum;
en = j;
st = s0;
}
if (sum < 0) {
sum = 0;
s0 = j + 1;
}
}
//sum2>0 && dp[i-1] + sum2 > max,则array[end_position~i]与array[0~i]合并才是当前数组最大子数组值
if (sum2 > 0 && dp[i-1]+sum2 > max) {
dp[i] = dp[i-1]+sum2;
end_position = st;
} else if (dp[i-1] > max) { //不能合并时,让dp[i]等于dp[i-1]和max的大者
dp[i] = dp[i-1];
} else {
dp[i] = max;
end_position = st;
}
}
for (int i = 0; i < len; i++)
cout << dp[i] << ' ';
}
int main() {
int A[] = {18, 20, -7, 12, -5, -22, 15, -4, 7};
int dp[SIZE];
MaxSubArray(A, dp, SIZE);
system("pause");
return 0;
}
array[]= {18, 20 , -7, 12} ,dp[2] = 38, end_position = 1(最大子数组的末尾下标, dp[2]表示array[0-2]的子数组最大值),则dp[3]的求法为,先看看-7+12 是否是大于0的,如果大于0,则18 20 -7 12合并后显然比dp[2]更大,应该合并,这时也得找出-7 12 这个数组最大子数组值,显然是12,拿12和合并后的比较取较大者,然后更新end_position。继续循环