Java实现斐波那契数列(递归、遍历、矩阵)

什么是斐波那契数列

其实很简单,能够理解为:
F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)
好比这样一个数列:一、一、二、三、五、八、1三、2一、3四、……
有兴趣能够看百度百科java


下面咱们就来实现,给定一个n,求f(n)的值web

递归解法

递归方法实际上是对方法定义完美的一对一实现,可是时间复杂度为O(2的n次方)
代码以下:svg

 /** * 采用递归的方式实现的 * 时间复杂度为O(2的N次方) * @param n * @return */ public static int f1(int n){ if (n == 0){ return 0; } if (n == 1){ return 1; } return f1(n-1) + f1(n-2); } /** * 采用递归的方式实现的 * 时间复杂度为O(2的N次方) * @param n * @return */ public static int f1(int n){ if (n == 0){ return 0; } if (n == 1){ return 1; } return f1(n-1) + f1(n-2); }

经过递归的代码发现,其实有很大一部分是重复算的,若是n趋近于无限大,那么就有一半是重复计算的。测试


遍历解法

遍历的方式相比于递归的方式时间复杂度好不少,为O(n)
代码以下:spa

 /** * 采用遍历的方式实现 * 时间复杂度为O(N) * @param n * @return */ public static int f2(int n){ int f0 = 0; if (n == 0) { return f0; } int f1 = 1; if (n == 1) { return f1; } int f2 = 0; for (int i=2; i<=n; i++){ f2 = f0 + f1; f0 = f1; f1 = f2; } return f2; } /** * 采用遍历的方式实现 * 时间复杂度为O(N) * @param n * @return */ public static int f2(int n){ int f0 = 0; if (n == 0) { return f0; } int f1 = 1; if (n == 1) { return f1; } int f2 = 0; for (int i=2; i<=n; i++){ f2 = f0 + f1; f0 = f1; f1 = f2; } return f2; }

可是遍历的方式还不是时间复杂度最低的解决方案!code


矩阵解法

实现的推导原理以下:
数列的递推公式为:f(1)=1,f(2)=2,f(n)=f(n-1)+f(n-2)(n>=3)
用矩阵表示为:
在这里插入图片描述
进一步,能够得出直接推导公式:
在这里插入图片描述
也有以下的推导(这一块不是很理解,懂的能够帮忙在评论区解释一下哈):
在这里插入图片描述
矩阵的解法时间复杂度为O(logn)
代码以下:xml

 /** * 采用矩阵的解法 * 时间复杂度为O(logN) * @param n * @return */ public static int f3(int n){ if (n == 0){ return 0; } int[][] fbnq = fbnq(n); return fbnq[0][1]; } /*矩阵处理核心代码*/ private static final int[][] UNIT = {{1,1}, {1,0}}; private static int[][] fbnq(int n){ if (n == 1){ return UNIT; } if (n % 2 == 0){ int[][] matrix = fbnq(n / 2); return matrixMultiply(matrix, matrix); }else { int[][] matrix = fbnq((n-1) / 2); return matrixMultiply(UNIT, matrixMultiply(matrix, matrix)); } } /*矩阵乘法*/ 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; } /** * 采用矩阵的解法 * 时间复杂度为O(logN) * @param n * @return */ public static int f3(int n){ if (n == 0){ return 0; } int[][] fbnq = fbnq(n); return fbnq[0][1]; } /*矩阵处理核心代码*/ private static final int[][] UNIT = {{1,1}, {1,0}}; private static int[][] fbnq(int n){ if (n == 1){ return UNIT; } if (n % 2 == 0){ int[][] matrix = fbnq(n / 2); return matrixMultiply(matrix, matrix); }else { int[][] matrix = fbnq((n-1) / 2); return matrixMultiply(UNIT, matrixMultiply(matrix, matrix)); } } /*矩阵乘法*/ 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) { for (int i = 0; i < 10; i++) { System.out.println("========"+i+"========"); System.out.println("递归方式:" + f1(i)); System.out.println("遍历方式:" + f2(i)); System.out.println("矩阵二分的方式:" + f3(i)); } } public static void main(String[] args) { for (int i = 0; i < 10; i++) { System.out.println("========"+i+"========"); System.out.println("递归方式:" + f1(i)); System.out.println("遍历方式:" + f2(i)); System.out.println("矩阵二分的方式:" + f3(i)); } }

奶思blog