zoukankan      html  css  js  c++  java
  • 【剑指offer】面试题九:斐波那契数列

    题目:写一个函数,输入 n,求斐波那契(Fibonaci)数列的第 n 项。斐波那契数列的定义如下:

    解法一、效率低下的递归解法

    代码如下:

     1 // Fanbonacci.c
     2 #include "stdio.h"
     3 #include "stdlib.h"
     4 
     5 long long Fabonacci(unsigned int n)
     6 {
     7     if(n <= 0)
     8         return 0;
     9 
    10     if(n == 1)
    11         return 1;
    12 
    13     return Fabonacci(n-1) + Fabonacci(n-2);
    14 }
    15 
    16 int main(int argc, char const *argv[])
    17 {
    18     int n = 10;
    19 
    20     long long sum = Fabonacci(n);
    21     printf("Fabonacci: %lld
    ", sum);
    22 
    23     return 0;
    24 }
    View Code

    该递归解法并不适合这道题目。因此这种解法存在很严重的效率问题。

    我们以求解 f(10) 为例来分析递归的求解过程。想求 f(10),需要先求得 f(9) 和 f(8)。同样的,想求得 f(9),需要先求得  f(8) 和  f(7) ······ 我们可以中树形结构来表示这样依赖关系。如下图:

    我们不难发现这棵树有很多结点是重复的,例如 f(8)、 f(7)、 f(6)、 f(5)··· 也就是说,树的右半部分都是重复计算的。试想一下当 n 是一个很大的数时,这样的重复计算量是很大的,因此递归解法会相当的慢。

    解法二:

    上述递归的方法之所以慢是因为重复的计算太多,那么有什么办法可以便面重复计算么?

    最简单的办法就是从下往上计算,首先根据  f(0)和 f(1)算出 f(2),再根据 f(1)和 f(2)算出 f(3)

    ······ 以此类推就可以算出第 n 项了,这样,这种算法的时间复杂度为 O(n)。

    实现代码如下:

     1 // Fibonacci.c
     2 #include "stdio.h"
     3 #include "stdlib.h"
     4 
     5 long long Fibonacci(unsigned int n)
     6 {
     7     int result[2] = {0, 1};
     8     if(n < 2)
     9         return result[n];
    10 
    11     long long FibMinusTwo = result[0];
    12     long long FibMinusOne = result[1];
    13 
    14     long long FibN = 0;
    15     int i;
    16     for(i = 2; i <= n; ++i)
    17     {
    18         FibN = FibMinusTwo + FibMinusOne;
    19 
    20         FibMinusTwo = FibMinusOne;
    21         FibMinusOne = FibN;
    22     }
    23 
    24     return FibN;
    25 }
    26 
    27 int main(int argc, char const *argv[])
    28 {
    29     int n = 10;
    30 
    31     long long sum = Fibonacci(n);
    32     printf("Fabonacci: %lld
    ", sum);
    33 
    34     return 0;
    35 }
    View Code

    编译与执行:

    1 gcc -o Fibonacci Fibonacci .c
    2 ./Fibonacci 

    斐波那契数列的应用:

    题目:一只青蛙一次可以跳上 1 级台阶,也可以跳上 2 级,求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
    我们可以用 2 * 1 的小矩形横着或者竖着去覆盖更大的矩形。请问用 8个 2*1的小矩形无重叠地覆盖一个 2*8 的大矩形,总共有多少种方法?

    本文完。

  • 相关阅读:
    冒泡排序
    MySql
    利用mybatis-generator自动生成代码
    SQL,HQL,CQL,JPQL了解
    mysql中的约束
    详解CRUD?
    什么是数据库ACID?
    建造者模式(Builder Pattern)
    Java中的设计模式
    java中的排序面试题
  • 原文地址:https://www.cnblogs.com/xfxu/p/4580368.html
Copyright © 2011-2022 走看看