递归算法以显示所有小于n的斐波那契数

时间:2018-10-26 11:32:41

标签: c++ algorithm recursion fibonacci

我需要编写递归算法,以显示所有小于n的斐波那契数。

例如

In:
n=400;
Out:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377

我写了这个

#include <iostream>
using namespace std;
int x=400;
int current_number;
int i=0;
int fibo(int n){
    if(n==0)
        return 0;
    if(n==1)
        return 1;
    else return fibo(n-2)+fibo(n-1);

}
int main(){
while(current_number<x){
    current_number=fibo(i);
if(current_number<x){
    cout<<fibo(i)<<" ";
    i++;
}
}
return 0;
}

但是我不确定这是否是解决此问题的正确方法。它必须是递归的,我不确定这种解决方案。有人可以给我一个更好的主意吗?

1 个答案:

答案 0 :(得分:0)

对于我来说,这对于必须使用递归算法的情况似乎是一个很好的解决方案,该算法专注于仅计算第n个斐波那契数而不打印它。

在这种情况下,我看到两个地方可以简化代码。

第一个是fibo功能。每次调用fibo recursivley都会降到0或1,然后在备份的途中开始将这些值加在一起。您调用了fibo函数两次,以计算获取下一个数字所需的一对数字。这是非常低效的,因为它导致使用相同的参数多次调用fibo函数。最后,您可以多次计算许多fibo数,这不是必需的。 (您从外面看不到它。)

为清楚起见,以下是向您展示该机制的图片:

           f(10)   = f(8) + f(9)
         /       \
     f(8)         f(9)
   /     \        /   \
 f(7)    f(6)   f(7)   f(8)

如您所见,对于i = 8和i = 7,f(i)函数被多次调用,对于更低的i-s,f(i)函数被调用的次数更多。

要消除此问题,您可以从零开始,然后一直向上走直到碰到边界为止。

// This function is the recursivly called function... 
int fiboRecursive(i, current, previous){
    // go on until i is zero
    if(i > 0){            
        // step over to the next one...
        return fiboRecursive(i-1, current+previous, current);
    } else {
        // return the result...
        return current;
    }
}

// use this function to calculate the ith fibonacci number
int fibo(i) {
    return fiboRecursive(i, 0, 1);
}

您可以改善代码的第二个地方是while循环:

而不是...

while(current_number<x){
    current_number=fibo(i);
    if(current_number<x){
        cout<<fibo(i)<<" ";
        i++;
    }
}

...你可以这样写:

current_number = 0;
while(current_number < x){
    cout << current_number << " ";
    current_number=fibo(++i);
}

优点是,您无需调用 fibo(i)两次,即可获得相同的结果,并且可以正常工作,因为第一个斐波那契数为0,因此您不必计算它。如果您不喜欢对第一个斐波那契数进行硬编码,请将此行放在while循环上方:

current_number = fibo(i);
while(current_number < x){
    cout << current_number << " ";
    current_number=fibo(++i);
}

但是,如果允许您也允许递归函数打印出数字,那么除了计算它们之外,还可以使用更有效的方法:

int printFibo(n, current, previous){
    // we only continue as long as the current fibonacci number is less than n
    if(current < n){
        // print out the current fibonacci number...
        cout << current << " ";

        // step over to the next one...
        if(current == 0){
            printFibo(n, 1, 0); // special starting case
        } else {
            printFibo(n, current+previous, current);
        }
    }
}

int main(){
    printFibo(400, 0, 1); // the 1 could be any number because in the first call in printFibo(...) we dont use the "previous" argument.
}

之所以更有效,是因为您最多打印出n个数字。您只需运行一次递归函数。