斐波那契数列第 n 项的值 f i b ( n ) fib(n) fib(n) 与递归树节点个数 G ( n ) G(n) G(n) 的关系证明:
先上结论: G ( n ) = 2 f i b ( n + 1 ) − 1 G(n)=2fib(n+1)-1 G(n)=2fib(n+1)−1
我们先看一下斐波那契数列的定义,如下:
f
i
b
(
n
)
=
{
0
,
n
=
0
1
,
n
=
1
f
i
b
(
n
−
1
)
+
f
i
b
(
n
−
2
)
,
n
≥
2
\begin{aligned} fib(n)= \begin{cases} 0&,n=0\\ 1&,n=1\\ fib(n-1)+fib(n-2)&,n\ge2 \end{cases} \end{aligned}
fib(n)=⎩⎪⎨⎪⎧01fib(n−1)+fib(n−2),n=0,n=1,n≥2
先由公式算出几个值,有:
f
i
b
(
0
)
=
0
,
f
i
b
(
1
)
=
1
,
f
i
b
(
2
)
=
1
,
f
i
b
(
3
)
=
2
,
f
i
b
(
4
)
=
3
,
f
i
b
(
5
)
=
5
,
f
i
b
(
6
)
=
8
\begin{aligned} fib(0)=0, fib(1)=1, fib(2)=1, fib(3)=2, fib(4)=3, fib(5)=5, fib(6)=8 \end{aligned}
fib(0)=0,fib(1)=1,fib(2)=1,fib(3)=2,fib(4)=3,fib(5)=5,fib(6)=8
以下是暴力递归实现斐波那契数列:
public static int fib(int n) {
if (n == 0 || n == 1) {
return n == 0 ? 0 : 1;
} else if (n < 0) {
throw new RuntimeException("请输入大于等于0的数");
}
return fib(n - 1) + fib(n - 2);
}
以下是该算法求解的递归树。
设 G ( n ) G(n) G(n) 为 f i b ( n ) fib(n) fib(n) 的递归树中节点个数,也就是说 G ( n ) G(n) G(n) 是调用该函数的次数。
看到该递归树,容易得出:
G
(
0
)
=
1
,
G
(
1
)
=
1
,
G
(
2
)
=
3
,
G
(
3
)
=
5
,
G
(
4
)
=
9
,
G
(
5
)
=
15
\begin{aligned} G(0)=1, G(1)=1, G(2)=3, G(3)=5, G(4)=9, G(5)=15 \end{aligned}
G(0)=1,G(1)=1,G(2)=3,G(3)=5,G(4)=9,G(5)=15
由数学归纳法容易证明
G
(
n
)
=
G
(
n
−
1
)
+
G
(
n
−
2
)
+
1
,
n
≥
2
G(n)=G(n-1)+G(n-2)+1,n\ge2
G(n)=G(n−1)+G(n−2)+1,n≥2
约定
T
(
n
)
=
O
(
G
(
n
)
)
T(n)=O(G(n))
T(n)=O(G(n)),
则有:
G
(
n
)
=
G
(
n
−
1
)
+
G
(
n
−
2
)
+
1
=
2
G
(
n
−
2
)
+
G
(
n
−
3
)
+
1
+
1
=
3
G
(
n
−
3
)
+
2
G
(
n
−
4
)
+
1
+
1
+
2
⋮
=
f
i
b
(
k
+
1
)
T
(
n
−
k
)
+
f
i
b
(
k
)
T
(
n
−
(
k
+
1
)
)
+
∑
i
=
0
k
f
i
b
(
i
)
\begin{aligned} G(n)=&G(n-1)+G(n-2)+1\\ =&2G(n-2)+G(n-3)+1+1\\ =&3G(n-3)+2G(n-4)+1+1+2\\ \vdots\\ =&fib(k+1)T(n-k)+fib(k)T(n-(k+1))+\sum_{i=0}^{k}fib(i)\\ \end{aligned}
G(n)===⋮=G(n−1)+G(n−2)+12G(n−2)+G(n−3)+1+13G(n−3)+2G(n−4)+1+1+2fib(k+1)T(n−k)+fib(k)T(n−(k+1))+i=0∑kfib(i)
我们知道该数列的递推式如下:
f
i
b
(
n
)
=
f
i
b
(
n
−
1
)
+
f
i
b
(
n
−
2
)
,
n
≥
2
fib(n)=fib(n-1)+fib(n-2),n\ge2
fib(n)=fib(n−1)+fib(n−2),n≥2
现将其作差使用累加法求和,过程如下:
f
i
b
(
n
)
−
f
i
b
(
n
−
1
)
=
f
i
b
(
n
−
2
)
f
i
b
(
n
−
1
)
−
f
i
b
(
n
−
2
)
=
f
i
b
(
n
−
3
)
⋮
f
i
b
(
2
)
−
f
i
b
(
1
)
=
f
i
b
(
0
)
\begin{aligned} &fib(n)-fib(n-1)=fib(n-2)\\ &fib(n-1)-fib(n-2)=fib(n-3)\\ &\vdots\\ &fib(2)-fib(1)=fib(0) \end{aligned}
fib(n)−fib(n−1)=fib(n−2)fib(n−1)−fib(n−2)=fib(n−3)⋮fib(2)−fib(1)=fib(0)
得到以下式子:
f
i
b
(
n
)
−
1
=
∑
i
=
0
n
−
2
f
i
b
(
i
)
fib(n)-1=\sum_{i=0}^{n-2}fib(i)
fib(n)−1=i=0∑n−2fib(i)
令
n
=
k
+
2
n=k+2
n=k+2 ,即有
∑
i
=
0
k
f
i
b
(
i
)
=
f
i
b
(
k
+
2
)
−
1
\sum_{i=0}^{k}fib(i)=fib(k+2)-1
i=0∑kfib(i)=fib(k+2)−1
ok,到这里,一切都准备就绪,接着把 G ( n ) G(n) G(n) 公式写下去就好了。
那么,现在令 k = n − 1 k=n-1 k=n−1,则
G ( n ) = f i b ( k + 1 ) T ( n − k ) + f i b ( k ) T ( n − ( k + 1 ) ) + ∑ i = 0 k f i b ( i ) = f i b ( k + 1 ) T ( 1 ) + f i b ( k ) T ( 0 ) + f i b ( k + 2 ) − 1 = f i b ( k + 1 ) + f i b ( k ) + f i b ( k + 2 ) − 1 = 2 f i b ( k + 2 ) − 1 = 2 f i b ( n + 1 ) − 1 \begin{aligned} G(n)=&fib(k+1)T(n-k)+fib(k)T(n-(k+1))+\sum_{i=0}^{k}fib(i)\\ =&fib(k+1)T(1)+fib(k)T(0)+fib(k+2)-1\\ =&fib(k+1)+fib(k)+fib(k+2)-1\\ =&2fib(k+2)-1\\ =&2fib(n+1)-1 \end{aligned} G(n)=====fib(k+1)T(n−k)+fib(k)T(n−(k+1))+i=0∑kfib(i)fib(k+1)T(1)+fib(k)T(0)+fib(k+2)−1fib(k+1)+fib(k)+fib(k+2)−12fib(k+2)−12fib(n+1)−1
举个例子,由递归树图中可以看出 G ( 5 ) = 15 G(5)=15 G(5)=15,
用公式算出 G ( 5 ) = 2 f i b ( 6 ) − 1 = 2 × 8 − 1 = 15 G(5)=2fib(6)-1=2\times8-1=15 G(5)=2fib(6)−1=2×8−1=15
可以看出该公式是正确的。
也就是说该暴力递归调用函数的次数为后一个值的 2 倍减 1。