什么是斐波那契数列
斐波那契数列指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2)
求数列中第n个数的值
本文总共总结了四种方法,欢迎大家补充。
方法一
- 首先最简单的就是直接法,利用迭代依次进行计算。
class Solution {
public:
int Fibonacci(int n)
{
if(n < 0) // 输入不符合要求
{
return -1;
}
if(n == 0 || n == 1)
{
return n;
}
int first = 0;
int second = 1;
int third = 1;
while(n-- > 2) // 循环n - 3次
{
first = second; // 先后移,后相加
second = third;
third = first + second;
}
return third;
}
};
方法二
- 第二种方法和第一种同样是利用了迭代的方法,不过只使用了两个临时变量。
class Solution
{
public:
int Fibonacci(int n)
{
if(n < 0)
{
return -1;
}
if(n == 0 || n == 1)
{
return n;
}
int first = 0;
int second = 1;
while(n-- > 1) // 循环n - 2 次
{
second = first + second; // second表示第三个值
first = second - first; // first表示第二个值
}
return j;
}
};
方法三
- 利用递归进行计算,因为根据定义在n > 2时,f(n) = f(n - 1) + f(n - 2),要想求得f(n)的值,就必须先求得f(n - 1)和f(n - 2)的值,以此类推,最终会在0或1处结束递归。
class Solution {
public:
int Fibonacci(int n)
{
if(n < 0)
{
return -1;
}
if(0 == n || 1 == n) // 递归出口
{
return n;
}
// 递归计算之前每一个的值并返回
return Fibonacci(n - 2) + Fibonacci(n - 1);
}
};
方法四
- (重点) 利用递归的方法解决问题看上去代码很简洁明了,但是当n的值较大时,它的效率明显变得很低。
这里一是因为递归层数过多,堆栈层数也会随之增多,甚至如果太大的话会致使程序中断;二是因为这个方法在计算的时候有很多无效的重复的计算,比如说如果要计算f(4),那么就要先计算f(3)和f(2),那么在计算f(3)的时候,就必须要先计算f(2)和f(1),这里就可以发现,f(2)被重复计算了,每次需要用到它的时候都会调用一次Fibonacci(2),但实际上这个值我们之前就已经计算过了,同理如果n的值足够大,那么这种重复的计算所产生的内存消耗是不可估量的。
解决方法:剪枝,可以将之前计算过的值都保存下来,之后需要使用的话可以直接查找,如果没有的话再去进行计算并保存。这里我们使用哈希表来存储。
class Solution {
private:
unordered_map<int, int> filter; // C++中unordered_map内部实现了哈希表
public:
int Fibonacci(int n)
{
if(n < 0)
{
return -1;
}
if(0 == n || 1 == n)
{
return n;
}
int pre = 0; //n - 1位置
int ppre = 0; //n - 2位置
// 利用find()函数在filter中查找是否已经存在了key == n - 1的数据
if(filter.find(n - 1) == filter.end()) // 没有
{
pre = Fibonacci(n - 1); // 递归
filter.insert({n - 1, pre}); // 将求得的结果插入到filter
}
else // 之前已经计算过f(n - 1)的值
{
pre = filter[n - 1];
}
if(filter.find(n - 2) == filter.end())
{
ppre = Fibonacci(n - 2);
filter.insert({n - 2, ppre});
}
else
{
ppre = filter[n - 2];
}
return ppre + pre; // 相加返回
}
};
结束
斐波那契数列是一个比较基础的问题,同时也是笔试面试中比较常见的问题,本文主要是学习一下常见的几种方法及剪枝的思想,希望这篇博客能够对你有所帮助。
第一次用博客的方式来记录学习,通过文字的方式来将算法的思想描述出来,确实跟自己看不太一样哈。