如何更快地生成Fibonacci

Meh*_*edi 13 c algorithm fibonacci

我是一名CSE学生,正准备参加编程竞赛.现在我正在研究Fibonacci系列.我有一个大小约为包含正整数的Kilo字节的输入文件.输入甲酸酯看起来像

3 5 6 7 8 0
Run Code Online (Sandbox Code Playgroud)

零表示文件结束.输出应该如此

2 
5 
8 
13 
21 
Run Code Online (Sandbox Code Playgroud)

我的代码是

#include<stdio.h>

int fibonacci(int n) {
  if (n==1 || n==2)
    return 1;
  else
    return fibonacci(n-1) +fibonacci(n-2);
}
int main() {
  int z;
  FILE * fp;    
  fp = fopen ("input.txt","r");    
  while(fscanf(fp,"%d", &z) && z) 
   printf("%d \n",fibonacci(z));
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

该代码适用于样本输入并提供准确的结果但问题是我的实际输入集它花费的时间超过我的时间限制.谁能帮我吗.

Kru*_*Kru 18

您可以简单地使用函数的尾递归版本,如果您对内存有限制,则返回最后两个斐波那契数字.

int fib(int n)
{
    int a = 0;
    int b = 1;
    while (n-- > 1) {
        int t = a;
        a = b;
        b += t;
    }
    return b;
}
Run Code Online (Sandbox Code Playgroud)

这是O(n)并且需要一个恒定的空间.


Xzh*_*hsh 14

你应该考虑一下memoization.

http://en.wikipedia.org/wiki/Memoization

它有一个解释和一个例子

  • @R - 但OP最好学习这种技术,因为它非常有价值.所以我不会说它根本不相关,而且在编程竞赛中尤为重要.在像斐波纳契这样的简单问题上学习技术是很好的,然后它可以应用于更困难的问题.此外,可以使用64位整数,然后可以存储更大的答案.或者在C#4.0或JAVA中,还有BigInteger,因此甚至可以存储非常大的数字. (2认同)

Teo*_*oae 12

您可以通过矩阵乘法来实现此目的,将矩阵提升为幂n,然后将其乘以向量.您可以在logaritmic时间将其提升到电源.

我想你可以在这里找到问题.它是罗马尼亚语,但你可以用谷歌翻译翻译它.这正是你想要的,以及它在那里列出的解决方案.

  • 它与斐波纳契数非常相关.例如,请参阅以下算法5:http://www.ics.uci.edu/~eppstein/161/960109.html每次询问此问题的变体时,这个答案经常出现在stackoverflow上(这是怎么回事我知道,链接只是谷歌搜索的第一个点击) (5认同)
  • @一个.Levy - 是的,它是相关的,你可以将某个矩阵提升到一定的幂并在'O(log n)`中得到斐波纳契数.我同意这个问题的答案非常模糊,而且链接很无用,因为了解矩阵乘法并不能真正帮助你看到解决方案.也许他打算链接到斐波那契页面.无论哪种方式,答案都没有错,所以我个人认为没有必要进行贬低. (4认同)

suk*_*kru 10

您的算法是递归的,并且大约具有O(2 ^ N)复杂度.

此问题已在stackoverflow上讨论过: Fibonacci Sequence的计算复杂性

在该特定讨论中还发布了更快的实施.


Dav*_*lle 7

在维基百科中,有一个公式可以给出Fibonacci序列中的数字,根本没有递归

  • @IVlad:那是无关紧要的.只要公式收敛,一旦收敛足够接近,舍入就是安全的(只要你注意有效数字,显然). (3认同)
  • 为什么没有确切的结果?这个公式实际上给出了确切的答案,因为你在计算时没有四舍五入。授予公式很复杂,但它的执行时间也与您要查找的数字无关。 (2认同)

dcp*_*dcp 6

使用memoization.也就是说,您缓存答案以避免不必要的递归调用.

这是一个代码示例:

#include <stdio.h>

int memo[10000]; // adjust to however big you need, but the result must fit in an int
                 // and keep in mind that fibonacci values grow rapidly :)

int fibonacci(int n) {
  if (memo[n] != -1)
    return memo[n];

  if (n==1 || n==2)
    return 1;
  else
    return memo[n] = fibonacci(n-1) +fibonacci(n-2);
}
int main() {
  for(int i = 0; i < 10000; ++i)
    memo[i] = -1;
  fibonacci(50);
}
Run Code Online (Sandbox Code Playgroud)