算法学习系列之找出斐波那契数

来源:互联网 发布:连锁店收银软件 编辑:程序博客网 时间:2024/05/18 03:58

特别说明:本文参考学习于Java语言程序设计进阶篇—Y.Daniel Liang著一书
欢迎大家一起学习交流,希望程序的世界有你相伴

题目

给出下标index,找出斐波那契数列下标为index的值,斐波那契数列为: {1,1,2,3,5,8…},前两位为1,随后的值均为在它前面的两个数的和。

解法

方法1

利用斐波那契数列的构造原理,我们很容易写出如下的递归算法解决该问题

    public static long fib1(int index) {        if (index == 0)            return 0;        else if (index == 1)            return 1;        else            return fib1(index - 1) + fib1(index - 2);    }

时间复杂度

令下标为n,假设T(n)表示找出fib1(n)的算法的复杂度,而c表示比较下标为0的数和下标为1的数耗费的常量时间,也就是说T(1)是c。因此

T(n)=T(n-1) + T(n-2) + c     <= 2*T(n-1) + c     <= 2*(2*T(n-2)+c) + c     = 2^2 *T(n-2) + 2c + c    ...    = 2^(n-1) *T(1) + (n-1)c + ... + c

可以发现T(n) 的O(2^n)。

可改进点

这个算法的效率并不高,递归的fib1()方法中存在的问题在于冗余地调用同样参数的方法。例如,为了计算fib1(4),要调用fib1(3)和fib1(2)。为了计算fib1(3),要调用fib1(2)与fib1(1)。注意fib1(2)被调用多次。我们可以通过避免这样重复调用同样的参数的fib1方法来提高算法效率。注意,一个新的斐波那契数是通过对数列中的前两个数相加得到的。如果用两个变量f0和f1来存储前面两个数,那么可以通过将f0和f1相加立即获得新数f2。这样,我们可以通过构建斐波那契数列的同时,得到该题的高效率的解法。

方法2

    public static long fib2(int index) {        long f0 = 0;        long f1 = 1;        long f2 = 1;        if (index == 0)            return f0;        else if (index == 1)            return f1;        else if (index == 2)            return f2;        for (int i = 3; i <= index; i++) {            f0 = f1;            f1 = f2;            f2 = f0 + f1;        }        return f2;    }

显然这样的算法的时间复杂度是O(n),这比方法1中的算法高效很多。

0 0
原创粉丝点击