/*
Solutions for the Maximum Subsequence Sum Problem
四种方法,时间复杂度依次递减:O(N^3)、O(N^2)、O(N log(N))、O(N)
*/
#include<vector>
#include<algorithm>
#define CATCH_CONFIG_MAIN
#include"catch.hpp"
using namespace std;
//生成测试数据,第一个参数为生成的数组,第二个参数为正确结果
pair<vector<int>, int> create_test_data (int len = 99);
//穷举法,时间复杂度为O(n^3)
int max_sub_sum0 (const vector<int>& data)
{
assert (data.size() > 0);
int max_sum = data[0];
for (int i = 0; i < data.size(); i++)
{
for (int j = i; j < data.size(); j++)
{
int this_sum = 0;
for (int k = i; k <= j; k++) { this_sum += data[k]; }
max_sum = max (this_sum, max_sum);
}
}
return max_sum;
}
//优化max_sub_sum0,使得时间复杂度为O(n^2)
int max_sub_sum1 (const vector<int> &data)
{
assert (data.size() > 0);
int max_sum = data[0];
for (int i = 0; i < data.size(); i++)
{
int this_sum = 0;
for (int j = i; j < data.size(); j++)
{
this_sum += data[j];
max_sum = max (max_sum, this_sum);
}
}
return max_sum;
}
//使用递归算法,算法的时间复杂度为N*log(N)
int max_sub_sum2 (const vector<int> &data, int left, int right)
{
if (left == right)
{
if (data[left] > 0) { return data[left]; }
else { return 0; }
}
int center = (left + right) / 2;
int left_max = max_sub_sum2 (data, left, center);
int right_max = max_sub_sum2 (data, center + 1, right);
int border_max_left = 0;
int buf = 0;
for (int i = center; i >= left; i--)
{
buf += data[i];
border_max_left = max (border_max_left, buf);
}
int border_max_right = 0;
buf = 0;
for (int i = center + 1; i <= right; i++)
{
buf += data[i];
border_max_right = max (border_max_right, buf);
}
return max (border_max_left + border_max_right, max (left_max, right_max));
}
//使用动态规划,使得时间复杂度为:O(N)
int max_sub_sum3 (const vector<int> &data)
{
int max_sum = 0;
int this_sum = 0;
for (auto &x : data)
{
this_sum += x;
max_sum = max (max_sum, this_sum);
if (this_sum < 0)
{
this_sum = 0;
}
}
return max_sum;
}
TEST_CASE ("test")
{
srand (time (nullptr));
for (int i = 0; i < 9; i++)
{
auto test = create_test_data (99 + (rand() % 100));
REQUIRE (test.second == max_sub_sum0 (test.first));
REQUIRE (test.second == max_sub_sum1 (test.first));
REQUIRE (test.second == max_sub_sum2 (test.first, 0, test.first.size() - 1));
REQUIRE (test.second == max_sub_sum3 (test.first));
}
}
//使用Data Structures and Algorithm Analysis in C++ 书中的代码作为标准求解正确答案
int maxSubSum4 (const vector<int> & a)
{
int maxSum = 0, thisSum = 0;
for (int j = 0; j < a.size(); ++j)
{
thisSum += a[j];
if (thisSum > maxSum)
{ maxSum = thisSum; }
else
if (thisSum < 0)
{ thisSum = 0; }
}
return maxSum;
}
pair<vector<int>, int> create_test_data (int len)
{
assert (len > 0);
vector<int> results (len);
srand (time (nullptr));
for (auto &e : results)
{
int rand_num = rand();
int sign = 1;
if ( (rand() % 1000) > 600) { sign = -1; }
e = sign * rand_num;
}
//assert ([&results]()->bool {for (auto &x : results) { if (x < 0) return true; } return false; }());
return make_pair (results, maxSubSum4 (results));
}