版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Lin_wj1995/article/details/82872644
什么是斐波那契数列
其实很简单,可以理解为:
F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)
比如这样一个数列:1、1、2、3、5、8、13、21、34、……
有兴趣可以看百度百科
下面我们就来实现,给定一个n,求f(n)的值
递归解法
递归方法其实是对方法定义完美的一对一实现,但是时间复杂度为O(2的n次方)
代码如下:
/**
* 采用递归的方式实现的
* 时间复杂度为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)
代码如下:
/**
* 采用遍历的方式实现
* 时间复杂度为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;
}
但是遍历的方式还不是时间复杂度最低的解决方案!
矩阵解法
实现的推导原理如下:
数列的递推公式为:f(1)=1,f(2)=2,f(n)=f(n-1)+f(n-2)(n>=3)
用矩阵表示为:
进一步,可以得出直接推导公式:
也有如下的推导(这一块不是很理解,懂的可以帮忙在评论区解释一下哈):
矩阵的解法时间复杂度为O(logn)
代码如下:
/**
* 采用矩阵的解法
* 时间复杂度为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));
}
}
奶思