剑指offer第二版-10.斐波那契数列

本系列导航:剑指offer(第二版)java实现导航帖

面试题10:斐波那契数列

题目要求:
求斐波那契数列的第n项的值。f(0)=0, f(1)=1, f(n)=f(n-1)+f(n-2) n>1

解法比较:
解法3,4将问题数学化,借助数学工具的推导,从根本上减低时间复杂度。

解法解法介绍时间复杂度空间复杂度
解法1依定义递归求解o(n^2)o(1)
解法2从0开始迭代求解o(n)o(1)
解法3借助等比数列公式o(logn)o(1)
解法4借助通项公式o(1)o(1)

代码:

package chapter2;

/**
 * Created by ryder on 2017/6/21.
 * 斐波那契数列
 * f(0)=0,f(1)=1,f(n)=f(n-1)+f(n-2) n>1
 */
public class P74_Fibonacci {

    // 依据原始概念的递归解法,时间复杂度o(n^2)
    public static int fibonacci1(int n){
        if(n<=0)
            return 0;
        if(n==1)
            return 1;
        return fibonacci1(n-1)+fibonacci1(n-2);
    }

    // 当前状态只与前两个状态有关。存储前两个值,计算后一个,迭代进行。时间复杂度o(n)
    public static int fibonacci2(int n){
        if(n<=0)
            return 0;
        if(n==1)
            return 1;
        int temp1 =0,temp2=1;
        int result = temp1 + temp2,i=3;
        while(i<=n){
            //也可用一个队列来完成下面三行的操作
            temp1 = temp2;
            temp2 = result;
            result = temp1+temp2;
            i++;
        }
        return result;
    }

    // 借助如下数学公式解决问题。矩阵乘法部分,可用递归解决,时间复杂度o(logn)
    // [ f(n)  f(n-1) ] = [ 1  1 ] ^ n-1   (当n>2)
    // [f(n-1) f(n-2) ]   [ 1  0 ]
    // 证明:
    // [ f(n)  f(n-1) ] = [ f(n-1)+f(n-2)  f(n-1)] = [ f(n-1)  f(n-2)] * [1 1]
    // [f(n-1) f(n-2) ]   [ f(n-2)+f(n-3)  f(n-2)]   [ f(n-2)  f(n-3)]   [1 0]
    // 得到如上递推式,所以
    // [ f(n)  f(n-1) ] = [ f(2)  f(1)] * [1 1]^n-2 = [1 1]^n-1
    // [f(n-1) f(n-2) ]   [ f(1)  f(0)]   [1 0]       [1 0]
    public static int fibonacci3(int n){
        int[][] start = {{1,1},{1,0}};
        return matrixPow(start,n-1)[0][0];
    }
    public static int[][] matrixPow(int[][] start,int n){
         if((n&1)==0){
             int[][] temp = matrixPow(start,n>>1);
             return matrixMultiply(temp,temp);
         }
         else if(n==1){
             return start;
         }
         else{
             return matrixMultiply(start,matrixPow(start,n-1));
         }
    }
    public static int[][] matrixMultiply(int[][] x,int[][] y){
        int[][] result = new int[x.length][y[0].length];
        for(int i=0;i<x.length;i++){
            for(int j=0;j<y[0].length;j++){
                int sum = 0;
                for(int k=0;k<x[0].length;k++){
                    sum += x[i][k]*y[k][j];
                }
                result[i][j] = sum;
            }
        }
        return result;
    }

    // 使用通项公式完成,时间复杂度o(1)
    // f(n) = (1/√5)*{[(1+√5)/2]^n - [(1-√5)/2]^n}
    // 推导过程可参考https://wenku.baidu.com/view/57333fe36bd97f192379e936.html
    public static int fibonacci4(int n){
        double gen5 = Math.sqrt(5);
        return (int)((1/gen5)*(Math.pow((1+gen5)/2,n)- Math.pow((1-gen5)/2,n)));
    }

    public static void main(String[] args){
        System.out.println(fibonacci1(13));
        System.out.println(fibonacci2(13));
        System.out.println(fibonacci3(13));
        System.out.println(fibonacci4(13));
    }
}

运行结果

233
233
233
233
    原文作者:ryderchan
    原文地址: https://www.jianshu.com/p/be764a696745#comments
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞