时间:2010-07-26 17:47:08

标签: c algorithm fibonacci

24 个答案:

答案 0 :(得分:18)

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

int fib(int n)
{
    int a = 0;
    int b = 1;
    while (n-- > 1) {
        int t = a;
        a = b;
        b += t;
    }
    return b;
}

这是O(n),需要一个恒定的空间。

答案 1 :(得分:14)

答案 2 :(得分:12)

答案 3 :(得分:10)

答案 4 :(得分:7)

答案 5 :(得分:6)

答案 6 :(得分:4)

没人提到2值堆栈数组版本,所以我只是为了完整性而做。

// do not call with i == 0
uint64_t Fibonacci(uint64_t i)
{
  // we'll only use two values on stack,
  // initialized with F(1) and F(2)
  uint64_t a[2] = {1, 1};

  // We do not enter loop if initial i was 1 or 2 
  while (i-- > 2)
    // A bitwise AND allows switching the storing of the new value
    // from index 0 to index 1.
    a[i & 1] = a[0] + a[1];

    // since the last value of i was 0 (decrementing i),
    // the return value is always in a[0 & 1] => a[0].
  return a[0];
}                                                                

这是一个O(n)常量堆栈空间解决方案,在使用优化进行编译时,其执行方式与memoization略有相同。

// Calc of fibonacci f(99), gcc -O2
Benchmark            Time(ns)    CPU(ns) Iterations
BM_2stack/99                2          2  416666667
BM_memoization/99           2          2  318181818

此处使用的BM_memoization只会初始化一次数组,并在每次其他调用时重复使用它。

2值堆栈数组版本在优化时与具有临时变量的版本完全相同。

答案 7 :(得分:3)

您还可以使用快速倍增法生成斐波那契系列 链接 - http://vinayakgarg.wordpress.com/2012/11/07/fastest-way-to-compute-fibonacci-number/

它实际上是从矩阵求幂方法的结果中得出的。

答案 8 :(得分:2)

答案 9 :(得分:1)

答案 10 :(得分:1)

在C#中:

        static int fib(int n)
        {
            if (n < 2) return n;
            if (n == 2) return 1;
            int k = n / 2;
            int a = fib(k + 1);
            int b = fib(k);
            if (n % 2 == 1)
                return a * a + b * b;
            else
                return b * (2 * a - b);
        }

答案 11 :(得分:1)

矩阵乘法,无浮点算术, O(log N)时间复杂度假设整数乘法/加法是在恒定时间内完成的。

这里是python代码

def fib(n):
    x,y = 1,1
    mat = [1,1,1,0]
    n -= 1
    while n>0:
        if n&1==1:
            x,y = x*mat[0]+y*mat[1], x*mat[2]+y*mat[3]
        n >>= 1
        mat[0], mat[1], mat[2], mat[3] = mat[0]*mat[0]+mat[1]*mat[2], mat[0]*mat[1]+mat[1]*mat[3], mat[0]*mat[2]+mat[2]*mat[3], mat[1]*mat[2]+mat[3]*mat[3]
    return x

答案 12 :(得分:1)

答案 13 :(得分:1)

答案 14 :(得分:0)

答案 15 :(得分:0)

在函数式编程中,有一种计算斐波纳契的特殊算法。该算法使用累积递归。累积递归用于最小化算法使用的堆栈大小。我认为它可以帮助您减少时间。如果你愿意,你可以试试。

int ackFib (int n, int m, int count){
    if (count == 0)
        return m;
    else
        return ackFib(n+m, n, count-1);
}



int fib(int n)
{
 return ackFib (0, 1, n+1);
}

答案 16 :(得分:0)

使用以下任何一个:递归的两个例子,一个用于循环O(n)时间,一个用黄金比率O(1)时间:

private static long fibonacciWithLoop(int input) {
    long prev = 0, curr = 1, next = 0;      
    for(int i = 1; i < input; i++){
        next = curr + prev;
        prev = curr;
        curr = next;
    }
    return curr;
}

public static long fibonacciGoldenRatio(int input) {
    double termA = Math.pow(((1 + Math.sqrt(5))/2), input);
    double termB = Math.pow(((1 - Math.sqrt(5))/2), input);
    double factor = 1/Math.sqrt(5);
    return Math.round(factor * (termA - termB));
}

public static long fibonacciRecursive(int input) {
    if (input <= 1) return input;
    return fibonacciRecursive(input - 1) + fibonacciRecursive(input - 2);
}

public static long fibonacciRecursiveImproved(int input) {
    if (input == 0) return 0;
    if (input == 1) return 1;
    if (input == 2) return 1;
    if (input >= 93) throw new RuntimeException("Input out of bounds");
    // n is odd
    if (input % 2 != 0) {
        long a = fibonacciRecursiveImproved((input+1)/2);
        long b = fibonacciRecursiveImproved((input-1)/2);
        return a*a + b*b;
    }

    // n is even
    long a = fibonacciRecursiveImproved(input/2 + 1);
    long b = fibonacciRecursiveImproved(input/2 - 1);
    return a*a - b*b;
}

答案 17 :(得分:0)

答案 18 :(得分:0)

答案 19 :(得分:0)

答案 20 :(得分:0)

using namespace std;

void mult(LL A[ 3 ][ 3 ], LL B[ 3 ][ 3 ]) {

     int i,

         j,

         z;

     LL C[ 3 ][ 3 ];

     memset(C, 0, sizeof( C ));

     for(i = 1; i <= N; i++)

         for(j = 1; j <= N; j++) {

             for(z = 1; z <= N; z++)

                 C[ i ][ j ] = (C[ i ][ j ] + A[ i ][ z ] * B[ z ][ j ] % mod ) % mod;
         }

     memcpy(A, C, sizeof(C));
};

void readAndsolve() {

    int i;

    LL k;

    ifstream I(FIN);
    ofstream O(FOUT);

    I>>k;

    LL A[3][3];
    LL B[3][3];

    A[1][1] = 1; A[1][2] = 0;
    A[2][1] = 0; A[2][2] = 1;

    B[1][1] = 0; B[1][2] = 1;
    B[2][1] = 1; B[2][2] = 1;

    for(i = 0; ((1<<i) <= k); i++) {

          if( k & (1<<i) ) mult(A, B);

          mult(B, B);
    }

    O<<A[2][1];
}

//1,1,2,3,5,8,13,21,33,...

int main() {

    readAndsolve();

    return(0);
}

答案 21 :(得分:0)

public static int GetNthFibonacci(int n)
    {
        var previous = -1;
        var current = 1;
        int element = 0;

        while (1 <= n--)
        {
            element = previous + current;
            previous = current;
            current = element;
        }

        return element;
    }

答案 22 :(得分:0)

这类似于之前给出的答案,但有一些修改。如其他答案中所述,记忆是另一种方法,但我不喜欢随着技术变化而缩放的代码(unsigned int的大小因平台而异)所以最高的值可以达到的顺序也可能不同,我认为记忆是丑陋的。

#include <iostream>

using namespace std;

void fibonacci(unsigned int count) {
   unsigned int x=0,y=1,z=0;
   while(count--!=0) {
      cout << x << endl;  // you can put x in an array or whatever
      z = x;
      x = y;
      y += z;
   }
}

int main() {
   fibonacci(48);// 48 values in the sequence is the maximum for a 32-bit unsigend int
   return 0;
}

此外,如果使用<limits>可以编写一个编译时常量表达式,它将为您提供序列中可以达到的任何整数数据类型的最大索引。

答案 23 :(得分:-1)

#include<stdio.h>
main()
{
 int a,b=2,c=5,d;
   printf("%d %d ");
do
{
   d=b+c;
     b=c;
    c=d;
   rintf("%d ");
  }