四種演算法實現最長連續子序列
阿新 • • 發佈:2021-01-11
#include <cstdio> #include <iostream> #include <vector> #include <cmath> #include <ctime> using namespace std; /* 產生長度為length的,元素為[-range,range)中隨機數的vector */ vector<int> randomVector(int range, int length) { srand(time(0)); vector<int> v(length); for (int i = 0; i < length; i++) v[i] = rand() % (range * 2) - range; return v; } /* 暴力破解 O(n^3) Sum(i,j) = Sum of seq[i,j] 對於每個i,j, 0 <= i <= j < seq.size() mcss = max(mcss,Sum(i,j)) */ int MCSS1(vector<int> seq) { int mcss = seq[0]; int tot = 0; for (int i = 0; i < seq.size(); i++) { for (int j = i; j < seq.size(); j++) { int sum = 0; for (int k = i; k <= j; k++) { sum += seq[k]; tot++; } mcss = max(mcss, sum); } } cout << "MCSS1,inner loop cnt: " << tot << endl; return mcss; } /* O(n^2)演算法 暴力破解演算法有很大的時間上的浪費 考慮已經求出Sum(i,j)的情況下再求Sum(i,j+1)可以直接利用之前的Sum(i,j)的結果加上seq[j+1],而不用重新計算 設S(i) = Sum(0,i),則Sum(i,j) = S(j) - S(i-1) 這裡就是利用了這一特性,記錄序列中每個i( 0 <= i < seq.size )的前i項和,去掉內層迴圈 */ int MCSS2(vector<int> seq) { int tot = 0; vector<int> S = { 0 }; for (int i = 0; i < seq.size(); i++) { S.push_back(seq[i] + S[i]); tot++; } int mcss = seq[0]; for (int i = 1; i < S.size(); i++) for (int j = i; j < S.size(); j++) { tot++; mcss = max(mcss, S[j] - S[i - 1]); } cout << "MCSS2,inner loop cnt: " << tot << endl; return mcss; } /* O(nlogn)演算法 MCSS3(seq,l,r) 返回在seq[l,r)中的最大連續子序列和,那麼MCSS3(seq,0,seq.size)為最終答案 設m為區間中間那個數,seq1為貫穿這個區間的最大連續子序列。 mcss = max(MCSS3(seq,l,m),MCSS3(seq,m,r),seq1) */ int MCSS3(vector<int> seq,int l,int r) { if (r - l == 1) return seq[l]; int m = (l + r) / 2; int lMax = seq[m - 1], lSum = 0; for (int i = m - 1; i >= l; i--) { lSum += seq[i]; lMax = max(lMax, lSum); } int rMax = seq[m], rSum = 0; for (int i = m; i < r; i++) { rSum += seq[i]; rMax = max(rMax, rSum); } return max(max(MCSS3(seq, l, m), MCSS3(seq, m, r)), lMax + rMax); } /* O(n)演算法 動態規劃 對於seq[i],它可以選擇加入前面的連續子序列,也可以選擇另開一個子序列。 當前面的連續子序列為負數時,選擇另開一個子序列比較好,得到一個包含seq[i]的區域性最大連續子序列 當前面的連續子序列為正數時,加入前面的子序列比較好,同樣得到一個包含seq[i]的區域性最大連續子序列 區域性最大子序列中最大的那個即為答案。 */ int MCSS4(vector<int> seq) { int mcss = seq[0],sum = seq[0]; for (int i = 1; i < seq.size(); i++) { // 如果 sum是負數,選擇另外開啟一個新的序列,因為前面的sum對它無幫助 if (sum < 0) { sum = 0; } sum += seq[i]; // sum = max(sum+seq[i],seq[i]); mcss = max(sum, mcss); } return mcss; } int main() { vector<int> a = randomVector(1023, 100);// MCSS = 198 cout << "MCSS1: " << MCSS1(a) << endl; cout << "MCSS2: " << MCSS2(a) << endl; cout << "MCSS3: " << MCSS3(a, 0, a.size()) << endl; cout << "MCSS4: " << MCSS4(a) << endl; return 0; }