1. 程式人生 > >斐波那契數列的求解

斐波那契數列的求解

斐波那契數列

  • 遞迴
  • 非遞迴

斐波那契數列遞推公式:
F ( n ) = { 1

, x = 0
1 , x =
1
F ( n 1 ) + F ( n 2 ) , x > = 2 F(n)=\begin{cases} 1,\quad x=0 \\\\ 1,\quad x=1 \\\\ F(n-1) + F(n-2) ,\quad x>=2 \end{cases}

遞迴演算法

long long Fib(int n) {
	if (n == 0 || n == 1)
		return 1;
	return Fib(n - 1) + Fib(n - 2);
}

或者是

long long Fib(int n) {
	return n <= 1 ? 1 : Fib(n - 1) + Fib(n - 2);
}

但是遞迴演算法的時間效率非常低,時間複雜度為O(N^2)
因為在此過程中存在大量的重複計算:比如在求解Fib(6)時,需要求解Fib(5)和Fib(4),而在計算Fib(7)時,用到了Fib(6)和Fib(5),都會重複計算。

非遞迴演算法

1.矩陣快速冪

矩陣快速冪就是將普通快速冪運算中的乘法運算換成了矩陣的乘法運算

const int N = 2;
int res[N][N];
void multi(long long a[][N], long long b[][N], int n) {
	memset(res, 0, sizeof(res));
	//矩陣乘法運算
	for (int i = 0; i < N; i++)
		for (int j = 0; j < N; j++)
			for (int k = 0; k < N; k++)
				res[i][j] += a[i][k] * b[k][j];

	//將結果複製到a陣列中,便於下一次迴圈的計算
	for (int i = 0; i < N; i++)
		for (int j = 0; j < N; j++)
			a[i][j] = res[i][j];
}

long long ans[2][2];
//計算a的n次冪
long long Fib4(long long a[][N], int n) {
	memset(ans, 0, sizeof(ans));
	//初始化ans陣列為1
	for (int i = 0; i < N; i++)
		ans[i][i] = 1;

	//快速冪,只是將簡單的乘法換成了矩陣的乘法運算
	while (n) {
		if (n & 1)
			multi(ans, a, n);
		multi(a, a, n);
		n >>= 1;
	}

	return ans[0][1];
}

2.迴圈

利用陣列實現

long long Fib(int n) {
	int arr[maxn];
	arr[0] = arr[1] = 1;
	for (int i = 2; i < n; i++) {
		arr[i] = arr[i - 1] + arr[i - 2];
	}

	return arr[n - 1];
}
3.公式
F_{n} = \frac{1}{\sqrt{5} }[(\frac{1+\sqrt{5} }{2})^n -  (\frac{1-\sqrt{5} }{2})^n]

時間複雜度O(1),但是涉及到浮點數,精度無法保證
程式碼略