斐波那契数列 logn 实现

2019-02-11  本文已影响0人  硕哒哒哒哒哒
对于fibonacci:

f(n) = \begin{cases} 0 & n = 0 \\ 1 & n = 1 \\ f(n-1)+f(n-2) & n\gt 1 \end{cases}

logn主要是基于计算一个数的n次方的方法。
计算一个数的n次方的方法:

a^n = \begin{cases} a^{n/2}\cdot a^{n/2} & n为偶数 \\ a^{(n-1)/2}\cdot a^{(n-1)/2}\cdot a & n为奇数 \\ \end{cases}

递归方式计算乘方,logn级别.

code:

public static int involution(int a, int n){
        if(n == 0) return 1;
        if(n <= 1 ) return a;//这里不考虑n小于0
        int temp = involution(a,n>>1);//计算a的n/2次方,这里为整除,为奇数时和(n-1)/2结果一致
        return n & 1 == 0 ? temp * temp : temp * temp * a;//
    }
fib原理:

\left[ \begin{matrix} f(n) & f(n-1) \\ f(n-1) & f(n-2) \end{matrix} \right] = \left[ \begin{matrix} 1 & 1 \\ 1 & 0 \end{matrix} \right]^{n-1}

可以使用数学归纳法证明,自己证!
使用前面介绍的方法简化计算矩阵的n次方,最终为logn级别!

code:

public class Fibonacci{
    public static int[][] matrixMul(int[][] a,boolean flag){//flag为true计算a的平方,flag为false计算a*init
        int[][] b = {{a[0][0],a[0][1]},{a[1][0],a[1][1]}};//a的拷贝
        if(flag){//a和a自身相乘
            a[0][0] = b[0][0]*b[0][0] + b[0][1]*b[1][0];
            a[0][1] = b[0][0]*b[0][1] + b[0][1]*b[1][1];
            a[1][0] = b[1][0]*b[0][0] + b[1][1]*b[1][0];
            a[1][1] = b[1][0]*b[0][1] + b[1][1]*b[1][1];
        }else{//a和init相乘
            a[0][0] = b[0][0] + b[0][1];
            a[0][1] = b[0][0];
            a[1][0] = b[1][0] + b[1][1];
            a[1][1] = b[1][0];
        }
        return a;
    }
    public static int[][] fibonacci(int[][] a,int n){
        if( n <= 1 ){//这里不考虑0和负数
            return a;
        }
        int[][] matXmat = matrixMul(fibonacci(a,n>>1),true);//计算a的n/2次方再做平方运算,
        return n & 1 == 0 ? matXmat : matrixMul(matXmat,false);//n为偶数时直接返回,n为奇数时,需要再乘上init矩阵
    }
    public static void main(String[] args){
        int[][] init = {{1,1},{1,0}};
        int[][] fib = fibonacci(init,5);//不考虑异常用例和0项
        System.out.println("斐波那契第6项:"+fib[0][0]);//从1计数 1 1 2 3 5 8
    }
}
上一篇下一篇

猜你喜欢

热点阅读