8.斐波那契数列

题目描述

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
n<=39

本题知识点: 递归

斐波那契

斐波那契数列来源于兔子繁殖问题,所以也叫兔子序列。指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N*)

递归实现

解题思路

递归实现就是套用 公式F(1)=1,F(2)=1,当n>=3时:F(n)=F(n - 1)+F(n - 2) 来实现的。
递归n次,时间复杂度O(2^n)

代码实现

java 代码

    /**
     * 递归求斐波那契数列
     *
     * @param n 
     * @return
     */
    public int fibonacci(int n) {
        if (n == 0) {
            return 0;
        } else if (n == 1 || n == 2) {
            return 1;
        }
        return fibonacci(n - 1) + fibonacci(n - 2);
    }



    public static void main(String[] args){
        System.out.println(fibonacci(6));
    }

Kotlin 代码

    /**
     * 递归求斐波那契数列
     *
     * @param n
     * @return
     */
    fun fibonacci(n: Int): Int {
        if (n == 0) {
            return 0
        } else if (n == 1 || n == 2) {
            return 1
        }
        return fibonacci(n - 1) + fibonacci(n - 2)
    }

    /**
     * 入口函数
     */
    fun main(args: Array<String>) {
         println(fibonacci(6))
    }

动态规划(迭代)实现

解题思路

因为斐波那契数列可以从左到右顺序的求出每一项的值,因此只需要顺序计算到n项即可,时间复杂度为O(n)的

代码实现

java 代码

    /**
     * 循环求斐波那契数列
     *
     * @param n
     * @return
     */
    public int fibonacci(int n) {
        int a = 1, b = 1, c = 0;
        if (n == 0) {
            return 0;
        } else if (n == 1 || n == 2) {
            return 1;
        } else {
            for (int i = 3; i <= n; i++) {
                c = a + b;
                a = b;
                b = c;
            }
        }
        return c;
    }

    public static void main(String[] args){
        System.out.println(fibonacci(6));
    }

Kotlin 代码

    /**
     * 循环求斐波那契数列
     *
     * @param n
     * @return
     */
    fun fibonacci(n: Int): Int {
        var a = 1
        var b = 1
        var c = 0
        if (n == 0) {
            return 0
        } else if (n == 1 || n == 2) {
            return 1
        } else {
            for (i in 3..n) {
                c = a + b
                a = b
                b = c
            }
        }
        return c
    }

    /**
     * 入口函数
     */
    fun main(args: Array<String>) {
        println(fibonacci(6))
    }

状态矩阵相乘求法

矩阵乘法

一个 m * p 的矩阵和一个 p * n的矩阵相乘得到一个 m * n的矩阵

\begin{bmatrix}
a&b \\  
c&d \\
\end{bmatrix}
\begin{bmatrix}
e&f \\  
g&h \\
\end{bmatrix}
=
\begin{bmatrix}
ae+bg&af+bh \\  
ce+dg&cf+dh \\
\end{bmatrix}

解题思路

这是一个时间复杂度为O(log n)的算法。因为斐波那契数列在n大于等于三的时候严格遵守递推数列f(n) = f(n-1) + f(n-2),而对于一个二阶的递推数列来说,我们可以用矩阵乘法来表示,且状态矩阵是2阶的方阵:

实现的推导原理如下:
数列的递推公式为:f(0)=0,f(1)=1,f(2)=2,
用矩阵表示为:

\begin{bmatrix}
f(n) \\  
f(n-1) \\
\end{bmatrix}
=
\begin{bmatrix}
1&1 \\  
1&0 \\
\end{bmatrix}
\begin{bmatrix}
f(n-1) \\  
f(n-2) \\
\end{bmatrix}

进一步,可以得出直接推导公式:

\begin{bmatrix}
f(n+1) \\  
f(n) \\
\end{bmatrix}
=
\begin{bmatrix}
1&1 \\  
1&0 \\
\end{bmatrix}
\begin{bmatrix}
f(n) \\  
f(n-1) \\
\end{bmatrix}
=
\begin{bmatrix}
1&1 \\  
1&0 \\
\end{bmatrix}^2
\begin{bmatrix}
f(n-1) \\  
f(n-2) \\
\end{bmatrix}
=
...
=
\begin{bmatrix}
1&1 \\  
1&0 \\
\end{bmatrix}^{n-1}
\begin{bmatrix}
f(2) \\  
f(1) \\
\end{bmatrix}


=
\begin{bmatrix}
1&1 \\  
1&0 \\
\end{bmatrix}^n
\begin{bmatrix}
f(1) \\  
f(0) \\
\end{bmatrix}
=
\begin{bmatrix}
1&1 \\  
1&0 \\
\end{bmatrix}^n
\begin{bmatrix}
1 \\  
0 \\
\end{bmatrix}

也可以推导为:

\begin{bmatrix}
f(n+1)&f(n)\\
f(n)&f(n-1)
\end{bmatrix}
=
\begin{bmatrix}
1&1 \\  
1&0 \\
\end{bmatrix}^n
=
\begin{bmatrix}
1&1 \\  
1&0 \\
\end{bmatrix}
\begin{bmatrix}
1&1 \\  
1&0 \\
\end{bmatrix}
...
\begin{bmatrix}
1&1 \\  
1&0 \\
\end{bmatrix}

(不是很懂)

代码实现

java 代码

    /**
     * 采用矩阵的解法
     * 时间复杂度为O(logN)
     *
     * @param n
     * @return
     */
    public int fibonacci(int n) {
        if (n == 0) {
            return 0;
        }
        int[][] fbnq = fbnq(n);
        return fbnq[1][0];
    }

    /**
     * 单元矩阵
     */
    private static final int[][] UNIT = {{1, 1}, {1, 0}};

    /**
     * 矩阵求斐波那契
     *
     * @param n
     * @return
     */
    private int[][] fbnq(int n) {
        if (n == 1) {
            return UNIT;
        }
        if (n % 2 == 0) {
            int[][] matrix = fbnq(n / 2);
            //相当于矩阵的n次幂(A^n/2  * A^n/2 = A^(n/2+n/2) = A^n
            return matrixMultiply(matrix, matrix);
        } else {
            int[][] matrix = fbnq((n - 1) / 2);
            //相当于矩阵的n次幂(A^(n-1)/2  * A^(n-1)/2 = A^((n-1)/2+(n-1)/2+1) = A^n
            return matrixMultiply(UNIT, matrixMultiply(matrix, matrix));
        }
    }

    /**
     * 矩阵乘法
     *
     * @param a 相乘的矩阵a
     * @param b 相乘的矩阵b
     * @return 矩阵相乘的结果
     */
    private static int[][] matrixMultiply(int[][] a, int[][] b) {
        int rows = a.length;
        int cols = b[0].length;
        int[][] matrix = new int[rows][cols];
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < b[0].length; j++) {
                for (int k = 0; k < a[i].length; k++) {
                    matrix[i][j] += a[i][k] * b[k][j];
                }
            }
        }
        return matrix;
    }

    public static void main(String[] args){
        System.out.println(fibonacci(6));
    }

Kotlin 代码

    /**
     * 采用矩阵的解法
     * 时间复杂度为O(logN)
     *
     * @param n
     * @return
     */
    private fun fibonacci(n: Int): Int {
        if (n <= 2) {
            return 1
        }
        val arr = fbnq(n);
        return arr[0][1]
    }

    /**
     * 单元矩阵
     */
    private val UNIT = arrayOf(intArrayOf(1, 1), intArrayOf(1, 0))
    /**
     * 矩阵求斐波那契
     *
     * @param n
     * @return
     */
    private fun fbnq(n: Int): Array<IntArray> {
        if (n == 1) {
            return UNIT
        }
        if (n % 2 == 0) {
            val matrix = fbnq(n / 2)
            return matrixMultiply(matrix, matrix)
        } else {
            val matrix = fbnq((n-1) / 2)
            return matrixMultiply(UNIT,matrixMultiply(matrix, matrix))
        }
    }

    /**
     * 矩阵乘法
     *
     * @param a 相乘的矩阵a
     * @param b 相乘的矩阵b
     * @return 矩阵相乘的结果
     */
    private fun matrixMultiply(a: Array<IntArray>, b: Array<IntArray>): Array<IntArray> {
        val row = a.size
        val col = b[0].size
        val matrix = Array<IntArray>(row) { IntArray(col) }
        for (i in 0 until row) {
            for (j in 0 until col) {
                for (k in a[i].indices) {
                    matrix[i][j] += a[i][k]*b[k][j]
                }
            }
        }
        return matrix
    }

    /**
     * 入口函数
     */
    fun main(args: Array<String>) {
        println(fibonacci(6))
    }

引用声明

该题目引用自
牛客网