【问题标题】:Algorithm function for fibonacci series [closed]斐波那契数列的算法函数
【发布时间】:2013-04-29 15:10:16
【问题描述】:

我不一定要寻找答案,但我正在寻找这个问题的要求。发现这个问题正在准备面试,但不确定他们在问什么?

编写遍历斐波那契数列并返回的函数 作为参数传入的索引。

【问题讨论】:

  • 啊....这更清楚了。谢谢。
  • 你看我的回答了吗?
  • 假设索引 i 是给定的。 a)通过 fib 系列运行:1 1(它没有说多远或什么,是吗?) b)返回 i

标签: algorithm fibonacci


【解决方案1】:

首先,您可以使用来自 wiki 的 link 更新有关斐波那契的基本数学信息。并查看this formula 进行快速计算。您可以在this 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(观察 herehere)。此外,添加整数很多 与对 a 取幂相比,计算成本更低且更精确 符号分数或浮点值

这是计算第 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)):

this link:

正如您已经怀疑的那样,这将非常相似。使用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's 或Moivre's 公式。

然后看看: 1-nth fibonacci number in sublinear time

【讨论】:

【解决方案2】:
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);
}

【讨论】:

    【解决方案3】:

    我对这个问题的解释不同......给定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;
    }
    

    【讨论】:

      【解决方案4】:

      在我看来,您被要求返回第 n 个斐波那契数,其中 n 是传递的参数。您可以采用各种方法来回答这个问题,而所有这些方法的时间复杂度和代码复杂度各不相同。

      方法一(使用递归) 一个简单的方法,就是上面给出的直接递归实现数学递归关系。

      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)。

      方法二(使用动态规划) 我们可以通过存储目前计算的斐波那契数来避免方法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 中使用的空间,因为这就是我们获得下一个 Fibannaci 数字序列所需的全部内容。

       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(利用矩阵 {{1,1},{0,1}} 的幂) 这另一个 O(n) 依赖于这样一个事实:如果我们将矩阵 M = {{1,1},{0,1}} 乘以 n 次(换句话说,计算幂(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)

      方法五(优化方法四) 方法 4 可以优化为在 O(Logn) 时间复杂度下工作。我们可以在之前的方法中进行递归乘法以获得幂(M,n)(类似于本文中所做的优化)

        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)。

      驱动程序: 主函数() { 诠释 n = 9; printf("%d", fib(9)); 获取字符(); 返回0; }

      参考资料: http://en.wikipedia.org/wiki/Fibonacci_number http://www.ics.uci.edu/~eppstein/161/960109.html

      【讨论】:

        【解决方案5】:

        这是一个措辞非常糟糕的问题,但您必须假设他们要求的是第 nth 个斐波那契数,其中n 作为参数提供。

        除了其他人列出的所有技术之外,对于n &gt; 1,您还可以使用golden ratio method,这比任何迭代方法都快。但正如问题所说的“遍历斐波那契数列”,这可能不符合条件。你可能还会把他们吓死。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-01-18
          • 2017-07-08
          • 2014-05-03
          • 2015-06-05
          • 1970-01-01
          • 2014-11-28
          相关资源
          最近更新 更多