2017-08-03 123 views
-1

我有一個遞歸函數。我想優化它少於10秒。更高的內存使用率不是問題。
在C++中優化遞歸

目前,在Linux上花費大約85秒,在Mac上花費了三倍。

我無法理解我能以何種方式繼續?

這裏是代碼:

using namespace std; 

double get_wall_time(){ 
    struct timeval time; 
    if (gettimeofday(&time,NULL)){ 
     // Handle error 
     return 0; 
    } 
    return (double)time.tv_sec + (double)time.tv_usec * .000001; 
} 

int fun(long long n) { 

    if (n < 0) { 
     cout << "Please enter valid number"; 
     return 0; 
    } 

    else if (n == 0 || n == 1) 
     return 1; 

    else if (n % 2 == 0) 
     return fun(n/2); 

    else if (n % 2 == 1) 
     return fun(n/2) + fun(n/2 - 1); 

    else 
     return 0; 
} 

int main() { 
    double begin = get_wall_time(); 
    cout << fun(123456789) << std::endl; 
    double end = get_wall_time(); 
    cout << "Time elapsed : " << double(end - begin); 
    return 0; 
} 

編輯:
如果n爲偶數,則返回f(n/2)
如果n是奇數,返回f(n/2)+f(n/2-1)

+8

只是爲了仔細檢查,您是否在優化開啓的情況下進行了編譯? – NathanOliver

+0

'else if(n%2)'和'else if(n%2 + 1)'。你確定你的意思嗎?如果'n'很奇怪,你想'回來玩(n/2)'?第二種情況 - 如果總是存在的話,因爲'n'是正數 – Justin

+0

'n%2'或'n%2 + 1'總是成立的,你永遠不會到達最後的'else'子句。 – Barmar

回答

1

我會用std::mapmemoize的結果,如所以:

std::map<long long, int>fun_results; 
int fun(long long n) { 
    try { 
     return fun_results.at(n); 
    } catch(const std::out_of_range&) { 

     if (n < 0) { 
      cout << "Please enter valid number"; 
      return 0; 
     } 

     else if (n == 0 || n == 1) 
      return fun_results[n] = 1; 

     else if (n % 2 == 0) 
      return fun_results[n] = fun(n/2); 

     else if (n % 2 == 1) 
      return fun_results[n] = fun(n/2) + fun(n/2 - 1); 

     else 
      return 0; 
    } 
} 

結果:

1332403 
Time elapsed : 0.000710011 
+0

你能給我指導它是如何工作的,爲什麼它如此之快? – user252514

+1

並不比維基百科關於[dynamic programming]的文章更好(https://en.wikipedia.org/wiki/ Dynamic_programming)和[memoization](https://en.wikipedia.org/wiki/Memoization)。簡而言之,您的算法一次又一次地計算相同的中間結果。通過存儲部分結果,我們保存了大量的遞歸調用。 –

+0

謝謝,羅布,這就是我想知道的,關鍵詞搜索和學習就像這裏,動態編程。 -ve marking wit霍特給予適當的答案讓我沮喪。 :( – user252514