【数据结构】斐波那契数列(Fibonacci sequence,黄金分割数列,兔子数列)

1,概念

指这样一个数列:1、1、2、3、5、8、13、21、34、……

F(1)=1F(2)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)

是一个线性递推数列。通向公式如下(又称为“比内公式”,是用无理数表示有理数的一个范例):
比内公式
注意

2,应用

1)输出前n项

现在要求输入一个整数n,请你输出斐波那契数列的第n项。n<=39。
思路:递归的效率低,使用循环方式(复杂度O(n))。

    public long fibonacci(int n) {
        long result=0;
        long preOne=1;
        long preTwo=0;
        if(n==0) {
            return preTwo;
        }
        if(n==1) {
            return preOne;
        }
        for (int i = 2; i <= n; i++) {
            result = preOne+preTwo;
            preTwo = preOne;
            preOne = result;
        }
        return result;
    }

笔者自己的代码:


    public int Fibonacci(int n) {

        int fun1 = 0, fun2 = 1;
        if (n == 0) return fun1;
        if (n == 1) return fun2;

        int i;
        for (i = 1; i + 2 < n; i += 2) {
            fun1 = fun1 + fun2;
            fun2 = fun1 + fun2;
        }
        if (i + 2 == n) fun1 = fun2 + fun1;
        return fun1 + fun2;
    }

2)青蛙跳台阶

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

思路:对于本题,前提只有 一次 1阶或者2阶的跳法。
a.如果两种跳法,1阶或者2阶,那么假定第一次跳的是一阶,那么剩下的是n-1个台阶,跳法是f(n-1);
b.假定第一次跳的是2阶,那么剩下的是n-2个台阶,跳法是f(n-2)
c.由a\b假设可以得出总跳法为: f(n) = f(n-1) + f(n-2)
d.然后通过实际的情况可以得出:只有一阶的时候 f(1) = 1 ,只有两阶的时候可以有 f(2) = 2
e.可以发现最终得出的是一个斐波那契数列:

           | 1, (n=1)
f(n) =     | 2, (n=2)
           | f(n-1)+f(n-2) ,(n>2,n为整数)

3)矩形覆盖

我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
思路:
斐波那契数列:
2*8的覆盖方法为 f(8),用一个1*2 小矩形覆盖最左边时有两个选择:竖着放一块,或者横着放两块(即f(1)=1;f(2)=2)。
竖着放一块时,记剩下区域覆盖有f(7)种;
横着放两块时,记剩下区域覆盖有f(6)种。
f(8)=f(7)+f(6)中覆盖方式。

    public int Fibonaccik(int n) {
        int number = 1;
        int sum = 1;
        if (n <= 0)
            return 0;
        if (n == 1) {
            return 1;
        }
        while (n-- >= 2) {//巧妙的存储了斐波那契数列
        //2,1   3,2   5,3……
            sum += number;
            number = sum - number;
        }
        return sum;
    }

4)超级青蛙跳

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
思路:其实是隔板问题,假设n个台阶,有n-1个空隙,可以用0~n-1个隔板分割,C(n-1,0)+C(n-1,1)+...+C(n-1,n-1)=2^(n-1),其中C表示组合。 有人用移位1<<--number,这是最快的。

组合运算:若表示在 n 个物品中选取 m 个物品,则如存在下述公式:C(n,m)=C(n,n-m)=C(n-1,m-1)+C(n-1,m)。
    public int jumpFloor1(int target) {
        return (int) Math.pow(2,target-1);
    }
    int jumpFloor2(int number) {//最快
        return 1<<(--number);
    }

你可能感兴趣的:(工作,编程素质)