关于
斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……
在数学上,斐波那契数列以如下被以递推的方法定义:
F
(
0
)
=
1
,
F
(
1
)
=
1
,
F
(
n
)
=
F
(
n
−
1
)
+
F
(
n
−
2
)
(
n
≥
2
,
n
∈
N
∗
)
F(0)=1,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)
F(0)=1,F(1)=1,F(n)=F(n−1)+F(n−2)(n≥2,n∈N∗)
1. 循环
/**
* 使用循环计算fibonacci
*
* @param n
* @return
*/
public static int fibLoop(int n) {
if (n <= 2)
return 1;
int a = 1, b = 1;
while (n-- != 2) {
b = a + b;
a = b - a;
}
return b;
}
2. 递归
/**
* 使用简单递归
*
* @param n
* @return
*/
public static int fibRecursive(int n) {
if (n == 1 || n == 2)
return 1;
return fibRecursive(n - 1) + fibRecursive(n - 2);
}
3. 带备忘录的递归
/**
* 带备忘录的fib
*
* @param n
* @return
*/
public static int fibRecord(int n) {
int[] rec = new int[n + 1];
int fib = fib(rec, n);
System.out.println(Arrays.toString(rec));
return fib;
}
/**
* 带备忘录的fib计算核心函数
*
* @param rec
* @param n
* @return
*/
private static int fib(int[] rec, int n) {
if (n == 1 || n == 2) {
return 1;
}
if (rec[n] > 0)
return rec[n];
rec[n] = fib(rec, n - 1) + fib(rec, n - 2);
return rec[n];
}
4.使用公式
公式就是
F
(
n
)
=
1
5
[
(
1
+
5
2
)
n
−
(
1
−
5
2
)
n
]
F(n)=\frac{1}{ \sqrt{5}}\left [\left ( \frac{1+\sqrt{5}}{2} \right )^n- \left ( \frac{1-\sqrt{5}}{2} \right )^n \right ]
F(n)=51[(21+5)n−(21−5)n]
/**
* 公式
*
* @param n
* @return
*/
public static int fibFormula(int n) {
double sqr = Math.sqrt(5);
double ret = (Math.pow((1 + sqr) / 2, n) - Math.pow((1 - sqr) / 2, n)) / sqr;
return (int) ret;
}
5. 使用矩阵乘法
原理就是
我们已经知道
F
(
0
)
=
1
,
F
(
1
)
=
1
,
F
(
n
)
=
F
(
n
−
1
)
+
F
(
n
−
2
)
(
n
≥
2
,
n
∈
N
∗
)
F(0)=1,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)
F(0)=1,F(1)=1,F(n)=F(n−1)+F(n−2)(n≥2,n∈N∗)
也即
F
(
n
+
1
)
=
F
(
n
)
+
F
(
n
−
1
)
F(n+1)=F(n)+F(n - 1)
F(n+1)=F(n)+F(n−1)
所以现在我们要构造一个矩阵, 要求里面含有这三项, 也就有了下面2x2的矩阵😎
[
F
(
n
+
1
)
F
(
n
)
F
(
n
)
F
(
n
−
1
)
]
\begin{bmatrix} F\left ( n+1 \right ) & F\left ( n \right )\\ F\left ( n \right )& F\left ( n-1 \right ) \end{bmatrix}
[F(n+1)F(n)F(n)F(n−1)]
现在我们希望有一个矩阵A使得:
[
F
(
n
+
1
)
F
(
n
)
F
(
n
)
F
(
n
−
1
)
]
×
A
=
[
F
(
n
+
2
)
F
(
n
+
1
)
F
(
n
+
1
)
F
(
n
)
]
\begin{bmatrix} F\left ( n+1 \right ) & F\left ( n \right )\\ F\left ( n \right )& F\left ( n-1 \right ) \end{bmatrix} \times A = \begin{bmatrix} F\left ( n+2 \right ) & F\left ( n+1 \right )\\ F\left ( n+1 \right ) & F\left ( n \right ) \end{bmatrix}
[F(n+1)F(n)F(n)F(n−1)]×A=[F(n+2)F(n+1)F(n+1)F(n)]
求得
A
=
[
1
1
1
0
]
A=\begin{bmatrix} 1&1 \\ 1&0 \end{bmatrix}
A=[1110]
令
T
(
n
)
=
[
F
(
n
+
1
)
F
(
n
)
F
(
n
)
F
(
n
−
1
)
]
T\left ( n \right ) = \begin{bmatrix} F\left ( n+1 \right ) &F\left ( n \right ) \\ F\left ( n \right )& F\left ( n-1 \right ) \end{bmatrix}
T(n)=[F(n+1)F(n)F(n)F(n−1)]
则
T
(
n
)
=
T
(
n
−
1
)
×
[
1
1
1
0
]
=
T
(
n
−
2
)
×
[
1
1
1
0
]
2
=
.
.
.
.
.
.
=
[
1
1
1
0
]
n
T\left ( n \right ) = T\left ( n-1 \right ) \times \begin{bmatrix} 1 &1 \\ 1 &0 \end{bmatrix} = T\left ( n-2 \right ) \times \begin{bmatrix} 1 &1 \\ 1&0 \end{bmatrix}^{2} =...... = \begin{bmatrix} 1&1 \\ 1& 0 \end{bmatrix}^{n}
T(n)=T(n−1)×[1110]=T(n−2)×[1110]2=......=[1110]n
故
/**
* 使用矩阵计算fib
* @param n
* @return
*/
public static int fibMatrix(int n) {
if (n <= 2)
return 1;
int[][] a = { { 1, 1 }, { 1, 0 } };
int[][] pow = matrixPow(a, n);
return pow[1][0];
}
/**
* 矩阵乘法 A(m*n)xB(n*p)=C(m*p)
*
* @param a
* @param b
* @return
*/
public static int[][] matrixMutiply(int[][] a, int[][] b) {
int[][] c = new int[a.length][b[0].length];
for (int i = 0; i < a.length; i++)
for (int j = 0; j < b[0].length; j++)
for (int k = 0; k < b.length; k++)
c[i][j] += a[i][k] * b[k][j];
return c;
}
/**
* 矩阵 快速幂
*
* 计算矩阵A的b次幂
*
* @param a
* @param b
* @return
*/
public static int[][] matrixPow(int[][] a, int b) {
int[][] c = new int[a.length][a.length];
// 单位阵
for (int i = 0; i < a.length; i++)
c[i][i] = 1;
while (b > 0) {
if ((b & 1) != 0) {
c = matrixMutiply(a, c);
}
a = matrixMutiply(a, a);
b >>= 1;
}
return c;
}
统一测试下
public void testFib() {
int n = 10;
System.out.println(fibLoop(n));
System.out.println(fibRecursive(n));
System.out.println(fibRecord(n));
System.out.println(fibFormula(n));
System.out.println(fibMatrix(n));
}