剑指offer笔记——面试题10:斐波那契数列
题目一:求斐波那契数列的第n项
问题描述
写一个函数,输入n,求斐波那契数列的第n项。斐波那契额数列的定义如下:
f
(
n
)
=
{
0
n
=
0
1
n
=
1
f
(
n
−
1
)
+
f
(
n
−
2
)
n
>
1
f(n)=\left\{ \begin{aligned} &0 & \ n = 0 \\ &1 & \ n = 1 \\ &f(n-1) + f(n-2) & \ n > 1 \end{aligned} \right.
f(n)=⎩⎪⎨⎪⎧01f(n−1)+f(n−2) n=0 n=1 n>1
代码
#include <iostream>
/**
* 斐波那契数列的第n项
* 效率很低的解法,挑剔的面试官不会喜欢
* 时间复杂度O(2^n)
*/
long long Fibonacci1(unsigned int n)
{
if(n == 0)
return 0;
else if(n == 1)
return 1;
else
return (Fibonacci1(n-1) + Fibonacci1(n-2));
}
// 函数声明
long long Fibonacci2(unsigned int, long long*);
/**
* 斐波那契数列的第n项
* 我们可以把已经得到的数列中间项保存起来
* 时间复杂度O(n),需要额外O(n)的空间复杂度
*/
long long Fibonacci2(unsigned int n)
{
long long Fibonacci[n+1]; // 注意这里是 n+1
for(unsigned int i = 0; i < n+1; i++)
Fibonacci[i] = -1; // -1表示该项元素未被计算过
return Fibonacci2(n, Fibonacci);
}
/**
* 斐波那契数列的第n项
* 我们可以把已经得到的数列中间项保存起来
* 内部方法
*/
long long Fibonacci2(unsigned int n, long long *Fibonacci)
{
if(n == 0)
Fibonacci[n] = 0;
else if(n == 1)
Fibonacci[n] = 1;
else
{
if(Fibonacci[n] == -1)
Fibonacci[n] = Fibonacci2(n-1, Fibonacci) + Fibonacci2(n-2, Fibonacci);
}
return Fibonacci[n];
}
/**
* 斐波那契数列的第n项
* 面试官期待的实用解法
* 从下往上计算
* 时间复杂度O(n)
*/
long long Fibonacci3(unsigned int n)
{
if(n == 0)
return 0;
else if(n == 1)
return 1;
else
{
long long fibNMinusOne = 1;
long long fibNMinusTwo = 0;
long long fibN = 0;
for(unsigned int i = 2; i <= n; i++)
{
fibN = fibNMinusOne + fibNMinusTwo;
fibNMinusTwo = fibNMinusOne;
fibNMinusOne = fibN;
}
return fibN;
}
}
int main()
{
std::cout << Fibonacci1(10) << std::endl; // 该方法计算第100项要等到天荒地老
std::cout << Fibonacci2(100) << std::endl;
std::cout << Fibonacci3(100) << std::endl;
}
运行结果
斐波那契数列的应用(考察数学建模能力)
青蛙跳台阶问题
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个n级的台阶总共有多少种跳法。
小矩形无重叠覆盖大矩形
我们可以用2×1的小矩形横着或者竖着去覆盖更大的矩形。请问用8个2×1的小矩形无重叠地覆盖一个2×8的大矩形,总共有多少种方法?