计算Fibonacci序列

问题描述:

计算Fibonacci序列


分析:

有两种方法,

第一种实现起来相当那个简单,但是做了大量重复的计算,比如计算fib(3)需要计算fib(2)和fib(1),但是计算fib(2)的时候还要计算一遍fib(1),复杂度为指数级。

所以第二种实现采用从小到大的计算方式,没有重复的计算。


代码实现:

Poor performance

package c02;

/**
 * @project: DataStructureAndAlgorithmAnalysis
 * @filename: Fibonacci
 * @version: 0.10
 * @author: Jimmy Han
 * @date: 21:52 2015/7/7
 * @comment: Bad performance fibonacci
 * @result: 89
 */
public class FibonacciBad {
    public static void main(String[] args) {
        System.out.println(fib(10));
    }

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


Good performance:

package c02;

/**
 * @project: DataStructureAndAlgorithmAnalysis
 * @filename: Fibonacci
 * @version: 0.10
 * @author: Jimmy Han
 * @date: 22:30 2015/7/7
 * @comment: Test Purpose
 * @result:
 */
public class Fibonacci {
    public static void main(String[] args) {
        System.out.println(fib(10));
    }

    public static long fib(long n){
        if(n < 2)
            return n;
        long f1 = 0;
        long f2 = 1;
        long res = 0;
        for(long i = 2; i <= n; i++){
            res = f1 + f2;
            f1 = f2;
            f2 = res;
        }
        return res;
    }

}


经网友指出有log(n)复杂度方法,验证如下:

package c02;

/**
 * @project: DataStructureAndAlgorithmAnalysis
 * @filename: FibonacciBetter
 * @version: 0.10
 * @author: Jimmy Han
 * @date: 23:29 2015/7/8
 * @comment: Test Purpose
 * @result:
 */
public class FibonacciBetter {
    public static void main(String[] args) {
        System.out.println(fib(10));
    }

    public static long fib(long n) {
        //通过研究fibonacci序列的规律:
        if (n ==0)
            return 0;
        if (n == 1 || n == 2)
            return 1;

        //如果n为奇数,则fib(n)为fib((n+1)/2)^2 + fib((n-1)/2)^2
        //比如,fib(9) = fib(5)^2 + fib(4)^2
        if (n % 2 == 1)
            return fib((n+1)/2)*fib((n+1)/2) + fib((n-1)/2)*fib((n-1)/2);
        //如果n为偶数,则fib(n)为fib(n/2)^2 + fib((n-2)/2)^2 + fib(n/2-1)*fib(n/2) + fib(n/2-2)*fib(n/2-1)
        //比如,fib(10) = fib(5)^2 + fib(4)^2 + fib(4)*fib(5) + fib(3)*fib(4)
        else
            return fib(n/2)*fib(n/2) + fib((n-2)/2)*fib((n-2)/2) + fib(n/2-1)*fib(n/2) + fib(n/2-2)*fib(n/2-1);
    }
}

结论:

方法3确实实现了O(logN)的复杂度,但是在实际测试中发现因为伴随大量的压栈操作,实际测试效果并不一定比方法2更快。当然可以通过把递归展开来降低运行时间,本人并没有进一步做测试,不过有一点可以确定,通过减少计算的数目,确实可以达到比方法2更快的速度。



你可能感兴趣的:(计算Fibonacci序列)