美文网首页
斐波那契数列 logn 实现

斐波那契数列 logn 实现

作者: 硕哒哒哒哒哒 | 来源:发表于2019-02-11 18:12 被阅读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
        }
    }
    

    相关文章

      网友评论

          本文标题:斐波那契数列 logn 实现

          本文链接:https://www.haomeiwen.com/subject/lvwqeqtx.html