求序列连续最大和问题,最优解当然应该是O(n)。
代码如下:
max_consecutive_sum() 是我写的,
maxsequence3() 是在下面链接上找到的
http://blog.csdn.net/sgbfblog/article/details/8032464
两个复杂度都是O(n)。感觉好像maxsequence3()的思路更简洁些。
divide_and_conquer() 参考了<<算法入门编程指南>>,分治法复杂度O(nlogn)。注意[x,y)是前开后闭区间。
测试了3个case,三个函数结果都一样。
#include <iostream>
using namespace std;
int arr[] = {199, -2223, -1, 7, 9, -66, 7, 8, 423, -24, -48, 7, 9, 22, 35, -8, 36, 67, -100, 9};
//int arr[] = {199, -2223, -1, 7, 9, -66, 7, 8, -423, -24, -48, 7, 9, 22, 35, -8, 36, 67, -100, 9};
//int arr[] = {-1, -2, -3, -77};
int max_consecutive_sum(int *a, int len) {
int s[len]={0};
s[0]=arr[0];
for (int i=1; i<len; i++) {
s[i]=s[i-1]+arr[i];
}
int min_index = 0;
int max_v=arr[0];
for (int i=1; i<len; i++) {
if (s[i-1] < s[min_index]) {
min_index = i-1;
}
if ((s[i]-s[min_index]) > max_v)
max_v = s[i]-s[min_index];
}
return max_v;
}
int maxsequence3(int a[], int len)
{
int maxsum, maxhere;
maxsum = maxhere = a[0]; //初始化最大和为a【0】
for (int i=1; i<len; i++) {
if (maxhere <= 0)
maxhere = a[i]; //如果前面位置最大连续子序列和小于等于0,则以当前位置i结尾的最大连续子序列和为a[i]
else
maxhere += a[i]; //如果前面位置最大连续子序列和大于0,则以当前位置i结尾的最大连续子序列和为它们两者之和
if (maxhere > maxsum) {
maxsum = maxhere; //更新最大连续子序列和
}
}
return maxsum;
}
int divide_and_conquer(int a[], int x, int y)
{
int sum, maxL, maxR, maxSub;
if (y == x+1)
return a[x];
int m = x + (y-x)/2;
maxSub = max(divide_and_conquer(a, x, m), divide_and_conquer(a, m, y));
sum = 0; maxL=arr[m-1];
for (int i=m-1; i>=x; i--) {
sum+=a[i];
maxL = max(maxL, sum);
}
sum = 0; maxR = arr[m];
for (int i=m; i<y; i++) {
sum+=a[i];
maxR = max(maxR, sum);
}
return max(maxSub, (maxL+maxR));
}
int main()
{
cout << "call max_consecutive_sum()"<<endl;
cout << max_consecutive_sum(arr, sizeof(arr)/sizeof(int))<<endl;
cout <<" call maxsequence3()"<<endl;
cout << maxsequence3(arr, sizeof(arr)/sizeof(int))<<endl;
cout <<" call divide_and_conquer()"<<endl;
cout << divide_and_conquer(arr, 0, sizeof(arr)/sizeof(int))<<endl;
return 0;
}