第19题:求解斐波拉契数列

欢迎转载,转载请务必注明出处:http://blog.csdn.net/alading2009/article/details/45456639
github:https://github.com/frank-cq/MyTest

第19题(数组、递归):定义Fibonacci数列如下:f(0)=0,f(1)=1,f(n)=f(n-1)+f(n-2)。输入n,用最快的方法求该数列的第n项。

最容易想到的是递归和迭代的求解方法,但是递归存在重复计算问题,n值越大,重复计算消耗越大。相比而言,迭代是一种较好的方法,时间复杂度O(n)。而效率最高的是矩阵方法,时间复杂度为O(logn),矩阵计算公式如下:

[fnfn1]=[1110]n1[10]
此时计算的核心转移到了计算幂矩阵上,采用分治法进行计算,分为幂指数为偶数和奇数两种情况。


代码

package test019;

/**
 * Created by cq on 2015/5/13.
 * 第19题(数组、递归):定义Fibonacci数列如下:f(0)=0,f(1)=1,f(n)=f(n-1)+f(n-2)。输入n,用最快的方法求该数列的第n项。
 */
public class Test019 {
    //一般递归方法,有重复计算
    public static int sumFibRecursion(int n){
        if (n == 0 || n == 1){
            return n;
        }

        return sumFibRecursion(n-1) + sumFibRecursion(n-2);
    }

    //迭代方法
    public static int sumFibIteration(int n){
        if (n < 0){
            System.out.println("n不应小于0!");
            return -1;
        }

        int fibN = n, fibN_1 = 1, fibN_2 = 0;
        for (int i=2; i<=n; i++){
            // f(n) = f(n-1) + f(n-2)
            fibN = fibN_1 + fibN_2;
            fibN_2 = fibN_1;
            fibN_1 = fibN;
        }

        return fibN;

//        int[] arr = {0,1};
//        for (int i=2; i<=n; i++){
//            if (i&1 == 0){
//                arr[0] = arr[0] + arr[1];
//            }
//            else {
//                arr[1] = arr[0] + arr[1];
//            }
//        }
//        return arr[n&2];
    }

    //矩阵递归方法,无重复计算,根据计算公式:(f(n),f(n-1))^T = A^(n-1) * (1,0)^T
    public static int sumFibMatrix(int n){
        if (n < 0){
            return -1; 
        }
        int[] matrix = {1,1,1,0};
        matrixPower(matrix,n-1);
        return matrix[0];
    }
    //分治法求矩阵的n次幂(效率就在这儿)
    public static void matrixPower(int[] matrix, int n){
        if (matrix == null || matrix.length != 4 || n <0){
            return;
        }
        if (n == 0){
            matrix[0] = matrix[1] = matrix[2] = matrix[3] = 1;
            return;
        }
        else if (n == 1){
            matrix[0] = matrix[1] = matrix[2] = 1;
            matrix[3] = 0;
            return;
        }
        //偶次幂,A^n = A^(n/2) * A^(n/2)
        if ((n&1) == 0){
            matrixPower(matrix,n/2);
            calculateMatrix(matrix,matrix,matrix);
        }
        //奇次幂,A^n = A^((n-1)/2) * A^((n-1)/2) * A
        else {
            matrixPower(matrix,(n-1)/2);
            calculateMatrix(matrix,matrix,matrix);
            calculateMatrix(matrix,new int[]{1,1,1,0},matrix);
        }

    }
    //二阶矩阵相乘(将二阶矩阵映射到一维数组上)
    public static void calculateMatrix(int[] matrixA, int[] matrixB, int[] matrix){
        if (matrixA == null || matrixA.length != 4 ||
                matrixB == null || matrixB.length != 4){
            return;
        }
        int value00 = matrixA[0]*matrixB[0] + matrixA[1]*matrixB[2];
        int value01 = matrixA[0]*matrixB[1] + matrixA[1]*matrixB[3];
        int value10 = matrixA[2]*matrixB[0] + matrixA[3]*matrixB[2];
        int value11 = matrixA[2]*matrixB[1] + matrixA[3]*matrixB[3];
        matrix[0] = value00;
        matrix[1] = value01;
        matrix[2] = value10;
        matrix[3] = value11;
    }

    public static void main(String[] args){

        System.out.println("使用递归求解斐波拉契数列结果:"+sumFibRecursion(10));

        System.out.println("使用迭代求解斐波拉契数列结果:"+sumFibIteration(10));

        System.out.println("使用矩阵求解斐波拉契数列结果:"+sumFibMatrix(10));
    }
}




执行结果

Connected to the target VM, address: '127.0.0.1:19344', transport: 'socket'
Disconnected from the target VM, address: '127.0.0.1:19344', transport: 'socket'
使用递归求解斐波拉契数列结果:55
使用迭代求解斐波拉契数列结果:55
使用矩阵求解斐波拉契数列结果:55

Process finished with exit code 0



ps:最近实验室的项目做得真是欲仙欲死,论文也写得蛋疼,好久没做题了。

原文地址:https://www.cnblogs.com/read-the-spring-and-autumn-annals-in-night/p/12041977.html