2015-01-05 56 views
0

我想從f_rec(遞歸函數)到f_iter(迭代函數),但我不能。 (我的邏輯是創建一個循環計算f_rec的結果(N-1)。從遞歸到迭代函數

int f_rec(int n) 
{ 
if(n>=3) 
    return f_rec(n-1)+2*f_rec(n-2)+f_rec(n-3); 
else 
    return 1; 
} 

int f_iter(int n) 
{ 
} 

我也認爲我對f_rec時間複雜度爲3 n次方,請糾正我,如果我錯了。

謝謝

+0

C或C++?答案可能非常不同。 –

+0

'int f_iter(int n){}'身體在哪裏? – 2501

+1

@ZoffDino我不知道它會有什麼不同。我的意思是沒有任何過度工程。 –

回答

0

以下是想法

int first=1,second=1,third=1; /* if n<=3 then the respective is the answer */ 
    for(i=4;i<=n;i++) 
    { 
    int next=first+2*second+third; 
    first=second; 
    second=third; 
    third=next; 
    } 
    cout<<"The answer is "<<next<<endl; 

內存O(1)和時間爲爲O(n)

編輯 你的遞歸函數確實是在指數時間,以保持它的線性就可以使數組F [N]使用 ,並使用記憶化。首先將F []初始化爲-1。

int f_rec(int n) 
    { 
     if(n>=3) 
     { 
      if(F[n]!=-1)return F[n]; 

      F[n]=f_rec(n-1)+2*f_rec(n-2)+f_rec(n-3); 
      return F[n];  
     } 

     else 
      return 1; 

}

+0

謝謝,非常感謝 – Oleg

0

只要保持三個變量與abc都等於把它們卷在

  • 啓動1
  • 在每一步new_aa + 2*b + c
  • 翻轉:new_cbnew_ba
  • 重複所需的步數
1

你總是可以從過去三年計算的最新值。剛開始從一開始計算,並始終保存最後三:

int f_iter (int n) { 
    int last3[3] = {1,1,1}; // The three initial values. Use std::array if C++ 

    for (int i = 3; i <= n; ++i) { 
     int new_value = last3[0] + 2 * last3[1] + last3[2]; 
     last3[0] = last3[1]; 
     last3[1] = last3[2]; 
     last3[2] = new_value; 
    } 
    return last3[2]; 
} 

這種解決方案需要O(1)內存和O(n)的運行時間。可能有一個公式可以用O(1)(最有可能)來計算這個公式,但我想爲了演示迭代技術,這是要走的路。

您的解決方案具有指數運行時間:每個額外的級別都會生成三個評估,因此您最終會得到O(3^n)操作和堆棧內存。

+0

Vielen Dank! 關於遞歸函數的n^3,我是否正確? – Oleg

+0

是的,你是對的,它是指數 – sashas

+0

我已經編輯了 – sashas

1

有兩個選項:

1)使用離散數學課程和推導公式。複雜性(如果@Sasha提到它的話)對於內存和算法都是O(1)。沒有循環,沒有遞歸,只是公式。

首先您需要找到特徵多項式並計算其根。假設我們的根源是r1,r2,r3,r4。那麼第n個元素是F(n) = A * r1^n + B * r2^n + C * r3^n + D * r4^n,其中A,B,C,D是一些未知係數。你可以使用你的初始條件找到這些係數(F(n) = 1 n < = 3)。

如果需要,我可以在俄羅斯解釋。

2)使用額外的變量來存儲中間值。就像@ 6052已經回答(他的回答非常快:))。

+0

我對O(1)算法的運行時間非常困惑,請你解釋一下嗎? 我以爲我不能比O(n)更好 – Oleg

+0

這是一個具有常係數的線性齊次遞歸關係。像斐波那契數列。所以你可以很容易地推導出公式。 –

+0

如果我正確地記得那些特徵多項式的根通常是實數(或更糟糕的是,非理性或超越),而不是整數,所以它們不能用於得到確切的答案。 – rcgldr

0

矯枉過正的位,但是這可以通過讓所述變量代表在展開循環變化,(鏈接)合併什麼Duff's device進入循環得到進一步的優化:

int f_iter(int n){ 
int a=1, b=1, c=1; 
    if(n < 3) 
     return(1); 
    switch(n%3){ 
     for(; n > 2; n -= 3){ 
      case 2: 
       b = c + 2*a + b; 
      case 1: 
       a = b + 2*c + a; 
      case 0: 
       c = a + 2*b + c; 
     } 
    } 
    return c; 
} 
+0

絕對有趣 – Oleg

+0

@Oleg - 即使對於64位無符號整數,n的最大值也是59,所以循環可以完全展開並使用57行(57例,59至3)的開關情況。對於32位有符號整數,n的最大值爲30(展開循環中的28行)。 ...或者循環可能部分展開爲3的倍數,如6,9,12 ......線。 – rcgldr