斐波那契数列是一列规律很简单、明显的数列,它的第0项是0,第1项是1,第2项是1,依此类推,之后每一项是之前两数的和。首几个数是:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946 ……(OEIS A000045)
编程实现
实现它最容易想到的方法,可以设一个数组,首两项是0和1,从n=2项起,每一项是之前两项之和,循环依次赋值,这里代码略去。下面介绍另几种实现方法。
用递归方法实现:
static long getItemRecursive(int index)
{
if (index < 1) return 0;
if (index == 1) return 1;
return getItemRecursive(index - 1) + getItemRecursive(index - 2);
}
这种实现方式最直观,但会很耗时,若方法名为fib,当index为5时,fib(5)的计算过程如下:
- fib(5)
- fib(4) + fib(3)
- (fib(3) + fib(2)) + (fib(2) + fib(1))
- ((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
- (((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
由上面可以看出,这种算法对于相似的子问题进行了重复的计算,因此不是一种高效的算法。实际上,该算法的运算时间是指数级增长的。
另外两种递归实现:
static long getItem2(int index)
{
return getItemRecursive2(0, 1, 0, index);
}
static long getItemRecursive2(int curr, int next, int currIndex, int index)
{
if (currIndex == index)
{
return curr;
}
else
{
return getItemRecursive2(next, curr + next, currIndex + 1, index);
}
}
static void getItemRecursive1(out long a2, out long a1, int index)
{
if (index <= 1)
{
a2 = 1;
a1 = 0;
}
else
{
long m2, m1;
getItemRecursive1(out m2, out m1, index - 1);
a1 = m2;
a2 = m2 + m1;
}
}
利用动态规划:
static long getItem(int index)
{
long n0 = 0, n1 = 1;
if (index < 1) return n0;
if (index == 1) return n1;
long sn;
for (int i = 2; i <= index; i++)
{
sn = n0 + n1;
n0 = n1;
n1 = sn;
//或者以下方法
//n1 = n0 + n1;
//n0 = n1 - n0;
//或者以下方法
//n0 = n1 ^ (n0 + n1);
//n1 = n1 ^ n0;
//n0 = n1 ^ n0;
}
return n1;
}
利用矩阵乘法、快速幂的实现:
这种方式当计算较大项(index大于65535)时,所花费的时间要比前面的方法花费的时间少至少一个数量级。
原理如下:
实现代码:
class FibonacciCalculator
{
struct FibonacciMatrixMultiple
{
public BigInteger a11;
public BigInteger a12;
public BigInteger a21;
public BigInteger a22;
public FibonacciMatrixMultiple(BigInteger p_a11, BigInteger p_a12, BigInteger p_a21, BigInteger p_a22)
{
this.a11 = p_a11;
this.a12 = p_a12;
this.a21 = p_a21;
this.a22 = p_a22;
}
public static FibonacciMatrixMultiple operator *(FibonacciMatrixMultiple mat1, FibonacciMatrixMultiple mat2)
{
return new FibonacciMatrixMultiple(
mat1.a11 * mat2.a11 + mat1.a12 * mat2.a21,
mat1.a11 * mat2.a12 + mat1.a12 * mat2.a22,
mat1.a21 * mat2.a11 + mat1.a22 * mat2.a21,
mat1.a21 * mat2.a12 + mat1.a22 * mat2.a22
);
}
}
struct FibonacciMatrix
{
public BigInteger a11;
public BigInteger a21;
public FibonacciMatrix(BigInteger p_a11, BigInteger p_a21)
{
this.a11 = p_a11;
this.a21 = p_a21;
}
public static FibonacciMatrix operator *(FibonacciMatrixMultiple mat1, FibonacciMatrix mat2)
{
return new FibonacciMatrix(
mat1.a11 * mat2.a11 + mat1.a12 * mat2.a21,
mat1.a21 * mat2.a11 + mat1.a22 * mat2.a21
);
}
}
private static FibonacciMatrix getFibonacciMatrix(int n)
{
FibonacciMatrix resultMatix = new FibonacciMatrix(1, 1);
FibonacciMatrixMultiple multiple = new FibonacciMatrixMultiple(1, 1, 1, 0);
while (n > 0)
{
if ((n & 1) == 1)
resultMatix = multiple * resultMatix;
n >>= 1;
if (n > 0)
multiple *= multiple;
}
return resultMatix;
}
public static BigInteger GetFibonacci(int index)
{
if (index < 1) return 0;
if (index == 1) return 1;
return getFibonacciMatrix(index - 2).a11;
}
}
JAVA实现:
1 class FibonacciCalculator { 2 static class FibonacciMatrixMultiple { 3 public BigInteger a11; 4 public BigInteger a12; 5 public BigInteger a21; 6 public BigInteger a22; 7 8 public FibonacciMatrixMultiple(BigInteger p_a11, BigInteger p_a12, 9 BigInteger p_a21, BigInteger p_a22) { 10 this.a11 = p_a11; 11 this.a12 = p_a12; 12 this.a21 = p_a21; 13 this.a22 = p_a22; 14 } 15 } 16 17 public static FibonacciMatrixMultiple Multiply( 18 FibonacciMatrixMultiple mat1, FibonacciMatrixMultiple mat2) { 19 return new FibonacciMatrixMultiple(mat1.a11.multiply(mat2.a11).add( 20 mat1.a12.multiply(mat2.a21)), mat1.a11.multiply(mat2.a12).add( 21 mat1.a12.multiply(mat2.a22)), mat1.a21.multiply(mat2.a11).add( 22 mat1.a22.multiply(mat2.a21)), mat1.a21.multiply(mat2.a12).add( 23 mat1.a22.multiply(mat2.a22))); 24 } 25 26 static class FibonacciMatrix { 27 public BigInteger a11; 28 public BigInteger a21; 29 30 public FibonacciMatrix(BigInteger p_a11, BigInteger p_a21) { 31 this.a11 = p_a11; 32 this.a21 = p_a21; 33 } 34 } 35 36 public static FibonacciMatrix Multiply2(FibonacciMatrixMultiple mat1, 37 FibonacciMatrix mat2) { 38 return new FibonacciMatrix(mat1.a11.multiply(mat2.a11).add( 39 mat1.a12.multiply(mat2.a21)), mat1.a21.multiply(mat2.a11).add( 40 mat1.a22.multiply(mat2.a21))); 41 } 42 43 private static FibonacciMatrix getFibonacciMatrix(int n) { 44 FibonacciMatrix resultMatrix = new FibonacciMatrix( 45 BigInteger.valueOf(1), BigInteger.valueOf(1)); 46 FibonacciMatrixMultiple multiple = new FibonacciMatrixMultiple( 47 BigInteger.valueOf(1), BigInteger.valueOf(1), 48 BigInteger.valueOf(1), BigInteger.valueOf(0)); 49 while (n > 0) { 50 if ((n & 1) == 1) 51 resultMatrix = Multiply2(multiple, resultMatrix); 52 n >>= 1; 53 if (n > 0) 54 multiple = Multiply(multiple, multiple); 55 } 56 return resultMatrix; 57 } 58 59 public static BigInteger GetFibonacci(int index) { 60 if (index < 1) 61 return BigInteger.valueOf(0); 62 if (index == 1) 63 return BigInteger.valueOf(1); 64 return getFibonacciMatrix(index - 2).a11; 65 } 66 }