web-dev-qa-db-ja.com

フィボナッチ数列のアルゴリズム関数

私は必ずしも答えを探しているわけではありませんが、この質問が求めていることを探しています。インタビューのために勉強しているこの質問を見つけましたが、彼らが何を求めているのかわかりませんか?

フィボナッチ数列を実行し、パラメーターとして渡されるインデックスを返す書き込み関数。

8
KingKongFrog

まず、wikiからこの link を使用して、フィボナッチに関する基本的な数学情報を更新できます。そして、高速計算のために この式 を見てください。そして、あなたはそれについてすべて このリンク で読むことができます。

これは、n番目のフィボナッチ数を計算する再帰関数であり、O(2 ^ n)時間です。

 int Fibonacci(int n) {  
        if (n == 0 || n == 1)  return n;
        else
        return Fibonacci(n - 1) + Fibonacci(n - 2); }

シーケンスの計算

コンピューターでフィボナッチ数列の値を実際に計算するという点では、元の反復関係f [n] = f [n-1] + f [n-2]を使用した方がよいと主張するかもしれません。私は同意する傾向があります。大きなnに対して直接閉形式の解を使用するには、多くの精度を維持する必要があります。たとえば、小数点以下9桁の場合でも、fn≈round(0.723606798⋅(1.618033989)n)は、n = 38までのみ有効です( here と比較して here を確認してください) )。また、整数の追加は、シンボリック分数または浮動小数点値の指数化よりも計算コストがはるかに少なく、正確です

これはn番目のフィボナッチ数を計算するためのより良いアイデアであり、O(n)時間です:

int Fibonacci(int n) { 
if(n <= 0) return 0;
if(n > 0 && n < 3) return 1;

int result = 0;
int preOldResult = 1;
int oldResult = 1;

for (int i=2;i<n;i++) { 
    result = preOldResult + oldResult;
    preOldResult = oldResult;
    oldResult = result;
}

return result;}

これはn番目のフィボナッチ数を計算する最良の方法であり、O(log(n))時間です。

このリンク:

すでに疑っているように、これは非常によく似た動作をします。 x * x行列のn乗を使用

|1 0 0 0  .... 1 1|
|1 
|  1
|    1
|      1
|        1
...................
...................
|          ... 1 0|

これは、この行列にベクトルを掛けると簡単に理解できます

f(n-1), f(n-2), ... , f(n-x+1), f(n-x)

その結果

f(n), f(n-1), ... , f(n-x+1)

行列のべき乗は、O(log(n))時間で実行できます(xが定数と見なされる場合)。

フィボナッチの再発については、閉じた式の解決策もあります。こちらをご覧ください http://en.wikipedia.org/wiki/Fibonacci_number 、BinetまたはMoivreの式を探します。

そして見てください:1 - サブリニア時間のn番目のフィボナッチ数

30
amin k

私には、n番目のフィボナッチ数(nは渡されたパラメーター)を返すように求められているようです。さまざまな方法を使用してこの質問に答えることができますが、これらはすべて時間の複雑さとコードの複雑さが異なります。

方法1(再帰を使用)上記の直接再帰的な実装の数学的再帰関係である単純な方法。

int fib(int n)
{
    if ( n <= 1 )
    return n;
    return fib(n-1) + fib(n-2);
}

時間の複雑さ:T(n) = T(n-1) + T(n-2)この実装は多くの繰り返し作業を行うことがわかります(次の再帰ツリーを参照)したがって、これはn番目のフィボナッチ数の不適切な実装です。

                     fib(5)   
                 /             \     
           fib(4)                fib(3)   
         /      \                /     \
     fib(3)      fib(2)         fib(2)    fib(1)
    /     \        /    \       /    \  

fib(2)fib(1)fib(1)fib(0)fib(1)fib(0)/\fib(1)fib(0)追加スペース:O(n)=機能呼び出しスタックサイズを考慮する場合、それ以外の場合はO(1)。

方法2(ダイナミックプログラミングを使用)これまでに計算されたフィボナッチ数を保存することで、方法1の繰り返し作業を回避できます。

int fib(int n)
{
     /* Declare an array to store fibonacci numbers. */
      int f[n+1];
      int i;

     /* 0th and 1st number of the series are 0 and 1*/
     f[0] = 0;
     f[1] = 1;

    for (i = 2; i <= n; i++)
    {
       /* Add the previous 2 numbers in the series
        and store it */
       f[i] = f[i-1] + f[i-2];
    }

    return f[n];
}

時間の複雑さ:O(n)余分なスペース:O(n)

方法3(スペース最適化方法2)前の2つの数値のみを保存することで、方法2で使用したスペースを最適化できます。これは、次のフィバンナッチ数を連続して取得するために必要なことだからです。

 int fib(int n)
 {
      int a = 0, b = 1, c, i;
      if( n == 0)
       return a;
      for (i = 2; i <= n; i++)
      {
        c = a + b;
        a = b;
       b = c;
    }
    return b;
  }

時間の複雑さ:O(n)余分なスペース:O(1)

方法4(matrx {{1,1}、{0,1}}の累乗を使用)これは別のO(n)これは、n回行列を乗算すると、 M = {{1,1}、{0,1}}自体に(つまり、power(M、n)を計算します)、行と列の要素として(n + 1)番目のフィボナッチ数を取得します( 0、0)結果の行列。

行列表現は、フィボナッチ数列に対して次の閉じた式を与えます。

  /* Helper function that multiplies 2 matricies F and M of size 2*2, and
    puts the multiplication result back to F[][] */
  void multiply(int F[2][2], int M[2][2]);

  /* Helper function that calculates F[][] raise to the power n and puts the
    result in F[][]
    Note that this function is desinged only for fib() and won't work as general
    power function */
  void power(int F[2][2], int n);

  int fib(int n)
  {
    int F[2][2] = {{1,1},{1,0}};
    if(n == 0)
        return 0;
    power(F, n-1);

    return F[0][0];
  }

  void multiply(int F[2][2], int M[2][2])
  {
    int x =  F[0][0]*M[0][0] + F[0][1]*M[1][0];
    int y =  F[0][0]*M[0][1] + F[0][1]*M[1][1];
    int z =  F[1][0]*M[0][0] + F[1][1]*M[1][0];
    int w =  F[1][0]*M[0][1] + F[1][1]*M[1][1];

    F[0][0] = x;
    F[0][1] = y;
    F[1][0] = z;
    F[1][1] = w;
  }

  void power(int F[2][2], int n)
  {
    int i;
    int M[2][2] = {{1,1},{1,0}};

    // n - 1 times multiply the matrix to {{1,0},{0,1}}
    for ( i = 2; i <= n; i++ )
        multiply(F, M);
  }

時間の複雑さ:O(n)余分なスペース:O(1)

方法5(最適化された方法4)方法4は、O(Logn)時間の複雑さで機能するように最適化できます。前の方法(この投稿で行われた最適化と同様)

  void multiply(int F[2][2], int M[2][2]);

  void power(int F[2][2], int n);

  /* function that returns nth Fibonacci number */
  int fib(int n)
  {
    int F[2][2] = {{1,1},{1,0}};
    if(n == 0)
      return 0;
    power(F, n-1);
    return F[0][0];
  }

  /* Optimized version of power() in method 4 */
  void power(int F[2][2], int n)
  {
    if( n == 0 || n == 1)
        return;
    int M[2][2] = {{1,1},{1,0}};

    power(F, n/2);
    multiply(F, F);

    if( n%2 != 0 )
       multiply(F, M);
  }

  void multiply(int F[2][2], int M[2][2])
  {
    int x =  F[0][0]*M[0][0] + F[0][1]*M[1][0];
    int y =  F[0][0]*M[0][1] + F[0][1]*M[1][1];
    int z =  F[1][0]*M[0][0] + F[1][1]*M[1][0];
    int w =  F[1][0]*M[0][1] + F[1][1]*M[1][1];

    F[0][0] = x;
    F[0][1] = y;
    F[1][0] = z;
    F[1][1] = w;
  }

時間の複雑さ:O(Logn)余分なスペース:O(Logn)関数呼び出しのスタックサイズを考慮する場合、そうでなければO(1)。

ドライバープログラム:int main(){int n = 9; printf( "%d"、fib(9)); getchar(); 0を返します。 }

参照: http://en.wikipedia.org/wiki/Fibonacci_numberhttp://www.ics.uci.edu/~eppstein/161/960109.html

13
Aman Chhabra

それは非常に言葉の悪い質問ですが、あなたは彼らがnを求めていると仮定する必要があります番目 nがパラメータとして提供されるフィボナッチ番号。

他の人が挙げたすべてのテクニックに加えて、n > 1黄金比法 を使用することもできます。これは、反復法よりも高速です。しかし、質問が「フィボナッチ数列を通り抜ける」と言っているように、これは適格ではないかもしれません。あなたもおそらく彼らを死ぬほど怖がらせるでしょう。

2
user207421
public static int fibonacci(int i){
if(i==0)
  return 0;

if(i==1)
   return 1;
return fib(--i,0,1);
}


public static int fib(int num,int pre,int prepre){
   if(num==0){
    return prepre+pre;
   }
    return fib(--num,pre+prepre,pre);
}
0
Dima

私は質問を別の方法で解釈します...入力としてnumberが与えられた場合、シリーズ内のその番号のindexは何ですか?例えばinput=5の場合、インデックスは5です(シーケンスが0 1 1 2 3 5の場合、インデックスは0で始まります)

このコードは次のとおりです(これはインデックスを返します)[免責事項: http://talkbinary.com/programming/c/fibonacci-in-c/ で指定されたコードから適応されます]

int Fibonacci(int n)
{
  if ( n == 0 )
    return 0;
  if ( n== 1 )
    return 1;

  int fib1 = 0; 
  int fib2 = 1;
  int fib = 0;
  int i = 0;

for (i = 2; ; i++ ) 
{

    fib = fib1 + fib2;
    if ( n == fib )
       break;
    fib1 = fib2;
    fib2 = fib;
}


  return i;
}
0
Bill