使用不同方法求解最大子序列之和問題
阿新 • • 發佈:2017-11-17
struct 一個 遞歸算法 def als main 復雜 mar false
/* 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)); }
使用不同方法求解最大子序列之和問題