斐波那契数列
数列:
f ( n ) = { 0 n = 0 1 n = 1 f ( n − 1 ) + f ( n − 2 ) n ≥ 2 f(n)=\left\{ \begin{array}{lcl} 0 & & {n=0}\\ 1 & & {n=1}\\ f(n-1)+f(n-2) & & {n\geq2} \end{array} \right. f(n)=⎩⎨⎧01f(n−1)+f(n−2)n=0n=1n≥2
递归实现形式
虽然用递归形式很简洁,但是因为重复计算,导致计算效率非常低,100几乎计算不出来。
//计算100时,根本算不出来
long long fibonacci1(unsigned int n)
{
if (n == 0) return 0;
if (n == 1) return 1;
return fibonacci1(n - 2) + fibonacci1(n - 1);
}
从下面的图可以看出来,f6,f5,f4都已经重复计算。
自下而上的计算方法
保留已经计算过程的 f(n-1)
和 f(n-2)
。大大提高计算效率
long long fibonacci2(unsigned int n)
{
if (n <= 0) return 0;
if (n == 1) return 1;
long long fMinus1 = 1;
long long fMinus2 = 0;
long long f = 0;
for (int i=2; i<=n; ++i)
{
f = fMinus1 + fMinus2;
fMinus2 = fMinus1;
fMinus1 = f;
}
return f;
}
斐波那契额数列的变体
青蛙跳台阶
一次可以跳一阶,也可以跳两阶。求跳上n个台阶的所有可能跳法f(n)。
跳n阶时,第一次跳有两种选择
- 跳1阶,剩下的跳法就是f(n-1)。
- 跳2阶,剩下的跳法就是f(n-2)。
故 f(n)=f(n-1)+f(n-2)。
青蛙跳阶的另一变体:
青蛙每次可以跳任意个,那么
- f(1) = 1
- f(2) = 2
- f(3) = f(2)+f(1)+1=4
- f(4) = f(3)+f(2)+f(1)+1 = 8 = f(3)+ f(3)
- f(n) = 2*f(n-1)= 2 n − 1 2^{n-1} 2n−1
1x2小矩形覆盖 2xn大矩形
1x2小矩形覆盖方法也有两种,横着和竖着
那第一次覆盖时,也有两种,
- 竖着覆盖,那么还剩的格子为 2x(n-1),剩下的覆盖方法为 f(n-1)
- 横着覆盖,那么还需要一个把小矩形下面的覆盖掉,这是确定的。那么剩下的格子数为2x(n-2),可能的覆盖方法为f(n-2)。
故 f(n)=f(n-1)+f(n-2)