Fibonacci数列的求解方法大致分为以下四种:
一、书本方法
适合向初学者演绎。
int fib(int n) {
if (n <= 0) {
return 0;
} else if (n == 1) {
return 1;
} else {
return fib(n – 1) + fib(n – 2);
}
}
缺点很明显,该算法的时间复杂度达到指数级:O(〖((1+√5)/2 )〗^n)。不适合处理数量很大的情形。
二、空间换时间
将中间结点存储到缓存中,避免了重复计算。
private static int fib(int n) {
if (n <= 0) {
return 0;
}
if (n == 1) {
return 1;
}
int result[] = new int[n];
result[0] = 0;
result[1] = 1;
for (int i = 2; i < n; i++) {
result[i] = result[i – 1] + result[i – 2];
}
return (result[n – 1] * result[n – 2]);
}
空间复杂度和时间复杂度均为O(n)
三、通项公式
缺点也很明显:计算机处理无理数(带根号)的精确性问题。
四、分治法
利用2的整数次方的特点,将其归结到二叉树。所以,时间复杂度得以降到lgn。
原理:[F(n) F(n-1)] = [F(n-1) F(n-2)] * [1 1 = [F(1) F(0)]*[1 1] ^(n-1)=
1 0] 1 0
// 矩阵的表示
class Matrix {
public long m00 = 0;
public long m01 = 0;
public long m10 = 0;
public long m11 = 0;
public Matrix(long m00, long m01, long m10, long m11) {
this.m00 = m00;
this.m01 = m01;
this.m10 = m10;
this.m11 = m11;
}
}
//矩阵的乘法
private static Matrix multiply(Matrix mb1, Matrix mb2) {
return new Matrix(
mb1.m00 * mb2.m00 + mb1.m01 * mb2.m10,
mb1.m00 * mb2.m01 + mb1.m01 * mb2.m11,
mb1.m10 * mb2.m00 + mb1.m11 * mb2.m10,
mb1.m10 * mb2.m01 + mb1.m11 * mb2.m11
);
}
//A^(n-1)
private static Matrix power(int n) {
if (n == 1) {
return new Matrix(1, 1, 1, 0);
} else if (n % 2 == 0) {//分治法
Matrix mb = power(n >> 1);
mb = multiply(mb, mb);
return mb;
} else if (n % 2 == 1) {
Matrix mb = power(n >> 1);
mb = multiply(mb, mb);
return multiply(mb, new Matrix(1, 1, 1, 0));
}
return null;
}
private static int test(int n) {
if (n <= 0) {
return 0;
} else if (n == 1) {
return 1;
} else {
return power(n – 1).m00; // 因为F(1)=1, F(0) = 0
}
}