斐波那契数列

关于递归和循环

1、通常基于递归的代码比基于循环的代码要简洁很多,更加容易实现,如果面试官没有特殊的要求,应聘者可以优先先采用递归的方法实现编程。

2、但是递归的缺点也很明显,递归时函数的调用自身,函数的调用是有时间和空间的消耗的,每次的函数调用都需要在内存栈中分配空间以用来保存参数,返回地址,临时变量,往栈中压入数据弹出数据都需要时间,故递归的实现效率一般不如循环。而且递归中有可能有大部分的计算都是重复的,导致性能变差。

3、递归也有可能引起严重的问题:调用栈溢出(每个进程的栈的容量是有限的,递归调用层级太,便会溢出)。

题目一:写一个函数,输入n,求斐波那契数列的第n项,斐波那契数列的定义如下:

     0,      n=0;

f(n)=   1,    n=1;

     f(n-1)+f(n-2)   n>1;

根据这个递归式,就可以直接写出相差不大的递归版本代码实现,但是这样的自上而下的递归导致大量的重复计算,如下图:

几乎大量的重复计算上述递归树中的非叶子结点值,导致效率下降,而对于大数字也会导致,递归栈溢出。

故更好的方法是从底向上计算,直到计算出f(n).先计算f(2)=1+0;,然后保存住f(2),f(1),用来求出f(3),然后同理的每次更新f(n-1)和f(n-2),直至求出f(n);

递归(自顶向下)和循环(自底向上)的代码实现如下:

 1 #include<iostream>
 2 using namespace std;
 3 long long Fibonacci(unsigned int n)//递归版本,大量的重复计算
 4 {
 5     if (n <= 0)
 6         return 0;
 7     else if (n == 1)
 8         return 1;
 9     else{
10         return Fibonacci(n - 1) + Fibonacci(n - 2);
11     }
12 }
13 long long Fibonacci1(unsigned int n)//自底向上去除重复计算
14 {
15     int result[2] = { 0, 1 };
16     if (n < 2)
17         return result[n];
18     long long fibNMinusone = 1;
19     long long fibNMinustwo = 0;
20     long long fibN = 0;
21     for (int i = 2; i <= n; i++)
22     {
23         fibN = fibNMinusone + fibNMinustwo;
24         fibNMinustwo = fibNMinusone;//注意这两行的先后顺序,一定不可变
25         fibNMinusone = fibN;
26     }
27     return fibN;
28 }
29 int main()
30 {
31     //cout << Fibonacci(40) << endl;//VS2013 update 4挂掉
32     cout << Fibonacci1(100) << endl;//依然可以计算
33     system("pause");
34     return 0;
35 }

以下是斐波那契数列的几种变形:

题目二:一只青蛙一次可以跳1级台阶,也可以调2级台阶,问青蛙跳上n级台阶有多少种跳法?

题目三:

原文地址:https://www.cnblogs.com/General-up/p/5414202.html