临近期末请勿抄袭,否则封号

3. 简单DP:斐波那契数 分享至QQ空间

发布时间: 2018-09-30 15:23:37.0 点击: 209

以下序列为斐波那契数列:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...

即满足F(n) = F(n-1)+F(n-2),其中F(0) = 0, F(1) = 1

图片1.png

方法一:递归

如果n为0或1,返回n,否则进行递归调用返回F(n-1)+F(n-2)。

int fib(int n)

{

    if (n <= 1)

        return n;

    return fib(n-1) + fib(n-2);

}

时间复杂度为指数增长,约O(2^N),因为有很多重复子问题(前文已有描述),空间复杂度:如果考虑栈开销为O(n),否则O(1)。

 

方法二:动态规划

int fib(int n)

{

    int f[10000];//n<10000

    int i;

    f[0] = 0;

    f[1] = 1;

    for (i = 2; i <= n; i++)

    {

        f[i] = f[i-1] + f[i-2];

    }

    return f[n];

}

可以将中间结果保存(记忆化或造表),时间和空间复杂度均为O(n):

 

方法三:空间优化(适合于只求一次)

只保存前面两个值,滚动计算后面的斐波那契数,时间复杂度O(n),空间O(1)。

int fib(int n)

{

    if(n<2)

        return n;

    int a = 0, b = 1, c, i;

    for (i = 2; i <= n; i++)

    {

        c = a + b;

        a = b;

        b = c;

    }

    return b;

}

 

方法四:快速矩阵幂

将斐波那契推导公式转化为矩阵:

根据快速矩阵幂,可以更高的效率计算出斐波那契数。

因为F(1)=1,F(0)等于0,因此矩阵:

 

的最左上角即为F(n),时间复杂度O(Log2N)。

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}};

  for (i = 2; i <= n; i++)

      multiply(F, M);

}

//快速幂

void fastpower(int F[2][2], int n)

{

  if( n == 0 || n == 1)

      return;

  int M[2][2] = {{1,1},{1,0}};

 

  fastpower(F, n/2);

  multiply(F, F);

 

  if (n%2 != 0)

     multiply(F, M);

}

 

int fib(int n)

{

  int F[2][2] = {{1,1},{1,0}};

  if (n == 0)

      return 0;

  fastpower(F, n-1);

 

  return F[0][0];

}



|返回 |   | 转到页头|
Copyright @ 2008-2024(浙ICP备2022001332号), TZOJ. All Rights Reserved.