题目:求斐波那契数列的第 斐波那契数列 - 图1 项。斐波那契数列的定义如下:

    斐波那契数列 - 图2

    斐波那契数列的定义对于大家来说应该很熟了,即斐波那契数列的第 斐波那契数列 - 图3 项等于前两项之和。

    1. public static int fibonacci(int n) {
    2. if (n <= 0) {
    3. return 0;
    4. } else if (n == 1 || n == 2) {
    5. return 1;
    6. }
    7. return fibonacci(n -1) + fibonacci(n - 2);
    8. }

    但是上面的程序有个很大的问题,就是运行的速度很慢,我们先看一下运行的时间,再来分析为何这么慢

    1. public static void main(String[] args) {
    2. long start = System.nanoTime();
    3. System.out.println(fibonacci(45));
    4. long end = System.nanoTime();
    5. System.out.println((end - start) / 1000000 + " ms");
    6. }

    结果如下

    1. 1134903170
    2. 4272 ms

    在我的电脑上,计算斐波那契数列第 斐波那契数列 - 图4 所需的时间为4272 ms,这时因为有重复的计算,我们在计算 斐波那契数列 - 图5#card=math&code=f%2845%29&height=20&width=39) 时,需要计算 斐波那契数列 - 图6#card=math&code=f%2844%29&height=20&width=39) 和 斐波那契数列 - 图7#card=math&code=f%2843%29&height=20&width=39),而在计算 斐波那契数列 - 图8#card=math&code=f%2844%29&height=20&width=39) 还需要计算 斐波那契数列 - 图9#card=math&code=f%2843%29&height=20&width=39),这样计算就重复了,它的时间复杂度为斐波那契数列 - 图10#card=math&code=O%282%5En%29&height=20&width=43)。

    现在我们考虑另一种解法,我们分析上面的计算是因为重复的计算,如果我们利用前面已有的结果,那么所需的时间即可大大减少,程序如下

    1. public static int fibonacci(int n) {
    2. if (n <= 0) {
    3. return 0;
    4. } if (n == 1 || n == 2) {
    5. return 1;
    6. }
    7. int firstNumber = 1;
    8. int secondNumber = 1;
    9. int result = 0;
    10. for (int i = 2; i < n; i++) {
    11. result = firstNumber + secondNumber;
    12. firstNumber = secondNumber;
    13. secondNumber = result;
    14. }
    15. return result;
    16. }

    上面的时间复杂度只有斐波那契数列 - 图11#card=math&code=O%28n%29&height=20&width=36),我们再次计算第 斐波那契数列 - 图12

    1. 1134903170
    2. 0 ms

    所需的时间连 1 ms 都不需要,速度相比上面提高的不是一星半点。

    题目:青蛙跳台阶。一只青蛙一次可以跳上 斐波那契数列 - 图13 级台阶,也可以跳上 斐波那契数列 - 图14 级台阶。求该青蛙跳上一个 斐波那契数列 - 图15 级的台阶总共有多少种跳法。

    其实这个问题仔细想想就可以发现,这道问题就是斐波那契数列的一个变体。考虑第 斐波那契数列 - 图16 级台阶,青蛙最后一步到达第 斐波那契数列 - 图17 级台阶只有两种方法,从 斐波那契数列 - 图18 级跳 斐波那契数列 - 图19 级,或者从 斐波那契数列 - 图20 级跳 斐波那契数列 - 图21 级,设青蛙跳上一个 斐波那契数列 - 图22 级台阶有 斐波那契数列 - 图23 种跳法,那么可以得到这样的关系式
    斐波那契数列 - 图24%20%3D%20f(n%20-%201)%20%2Bf(n%20-%202)%0A#card=math&code=f%28n%29%20%3D%20f%28n%20-%201%29%20%2Bf%28n%20-%202%29%0A&height=20&width=198)

    这个式子不就是斐波那契数列的通项嘛,所以程序的写法也是一样的,不过它们的初始条件不一样,简单分析就可以得到

    斐波那契数列 - 图25%20%3D%201%20%5C%5C%5C%5C%0Af(2)%20%3D%202%0A#card=math&code=f%281%29%20%3D%201%20%5C%5C%5C%5C%0Af%282%29%20%3D%202%0A&height=45&width=724)

    具体的程序参考上面。