《剑指offer》Java学习录:面试题9:斐波那契数列

面试题 9:斐波那契数列

题目:

写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项。斐波那契数列的定义如下:
f(n)={0,n=01,n=1f(n1)+f(n2),n>1 f(n)= \begin{cases} 0, & \text{$n = 0$}\\ 1, & \text{$n = 1$}\\ f(n - 1) + f(n - 2),& \text{$n > 1$} \end{cases}

分析

首先想到的是利用递归来解,如:

public static int fibonacci(int n) {
    if (n <=0 ) {
        return 0;
    } else if (n == 1) {
        return 1;
    } else {
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
}

该解法确实简单,很快就可以实现。让我们来分析一下:

我们以求解f(10)f(10)为例分析求解过程。想要求f(10)f(10)就的求f(9)f(9)f(8)f(8),想要求f(9)f(9)需要先求f(8)f(8)f(7)f(7),同样想要求f(8)f(8),又得先求f(7)f(7)f(6)f(6) … 我们可以以树结构表达这种依赖关系。
在这里插入图片描述
不难发现,书中有很多节点重复,这意味着计算量会随着n的增大而急剧增大,事实上,用递归计算的时间复杂度是以n的指数递增的。我试了一下,当n为45时,就能很明显的发现获得结果需要等待一小会儿了。

改进

上面递归代码之所以慢是因为重复计算过多,当我们的递归从小往大计算时,第n次的结果总是前两次之后,而前两次刚好再前面两次已经计算过并记录了。

public static void main(String args[]) {
    System.out.println(fibonacci1(1000));
}

public static int fibonacci1(int n) {
    int[] result = {0, 1};
    if (n < 2) {
        return result[n];
    }
    int preNumberOne = 1;
    int preNumberTwo = 0;
    int number = 0;
    for (int i = 2; i <= n; i++) {
        number = preNumberOne + preNumberTwo;
        preNumberTwo = preNumberOne;
        preNumberOne = number;
    }
    return number;
}

斐波那契数列的运用:青蛙跳台阶

题目

一只青蛙可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个n级台阶总共有多少种跳法。

分析

首先考虑最简单的情况,如果只有一级台阶,青蛙第一次跳的时候,显然只有一种跳法。如果有2级,有两种跳法:一种是跳一级、一种是跳两级。

再看一般情况,假如青蛙跳n级台阶总共有F(n)F{(n)} 种跳法,当n > 2 时,第一次有两种不同的选择:1. 只跳1级,此时跳法数据等于后面剩下的n - 1级台阶的跳法数目,即 $ F(n - 1)2.2n2。2. 只跳2级,此时跳法数目等于后面剩下的n - 2级台阶的跳法数目,即 F(n - 2)$ 。因此n级台阶的不同跳法总数为F(n)=F(n1)+F(n2)F(n) = F(n - 1) + F(n - 2)。不难看出,这就是一个斐波那契数列。

斐波那契数列的运用:矩形覆盖

题目

我们可以用2 x 1的小矩形横着或者竖着去覆盖更大的矩形。请问用8个 2 x 1的小矩形无重叠地覆盖一个 2 x 8的大巨星,总共有多少种方法?矩形如图:

fugai
在这里插入图片描述

分析

先把2 x 8的覆盖方法次数记为F(8)F(8) , 用1x2的矩形第一次覆盖到2x8上有两种方式:

  1. 竖着盖在最左边,此时的覆盖次数有F(7)F(7)
  2. 横着覆盖最左上角, 此时覆盖次数记为F(6)F(6)
  3. 所以,对于2x8的矩形区域,F(8)=F(7)+F(6)F(8) = F(7) + F(6)

显然,又是一个斐波那契数列。

结语

斐波那契数列相关题目特征:

  1. 每个步骤有两种不同的操作。
  2. 有0和1两个解。
  3. 经过两个不同操作后,问题规模将会得到不同程度的降低。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章