Fibonacci数列求解

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

}

}

点赞