斐波那契数列是一列规律很简单、明显的数列,它的第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)的计算过程如下:

  1. fib(5)
  2. fib(4) + fib(3)
  3. (fib(3) + fib(2)) + (fib(2) + fib(1))
  4. ((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
  5. (((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 }
View Code

相关文章: