代码改变世界

面试题3:斐波那契数列与爬楼梯

2013-10-07 14:14  Keiven_LY  阅读(2991)  评论(0编辑  收藏  举报

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

看到这个最简单想到的方法是采用递归来实现

功能函数:

long long Fibonacci(int n)
{
    if(n<0)
        return;
    if(n==0)
        return 0;
    if(n==1)
        return 1;
    if(n>1)
        return Fibonacci(n-1)+Fibonacci(n-2);
}

程序分析:

采用递归来解决这一问题,会带来严重的效率问题。比如:要求f(10),如下图所示

可以看到,上面图示中有很多重复结点,而且重复结点会随着n的增大而急剧增加,意味着计算量也会随着n的增大而急剧增加。

针对上述递归方法的低效率,做如下改进:

思路1:可以把已经得到的数列中间项保存起来,如果下次需要计算的时候先查找一下,如果之前已经计算过就不用重复计算了。

思路2:可以从下往上计算,首先根据f(0)和f(1)算出f(2),再根据f(1)和f(2)算出f(3)......依次类推,直到算出f(n)即可。

功能函数:

long long one=0;
long long two=1;
long long result=0;

long long Fibonacci(int n)
{
    int i;
    if(n<0)
        return;
    if(n==0)
        return 0;
    if(n==1)
        return 1;

    for(i=2;i<=n;i++)
    {
        result=one+two;
        one=two;
        two=result;
    }
    return result;
}

注意:如果将长整型变量one、two、result放在函数体内,变为局部变量,编译时出错。

        原因是:编译器栈空间有限 分配不了那么大的局部变量。定义在外面,即为全局变量,是存储在全局区,不在栈区

测试程序:

int main()
{
    int a,b,sum=0;

    printf("递归方法\n");
    printf("请输入一个数:");
    scanf("%d",&a);
    sum=Fibonacci_1(a);
    printf("输入的数%d的斐波那契数列的第%d项为:%d\n",a,a,sum);
    printf("\n");

    printf("非递归方法\n");
    printf("请输入一个数:");
    scanf("%d",&b);
    sum=Fibonacci_2(b);
    printf("输入的数%d的斐波那契数列的第%d项为:%d\n",b,b,sum);
    printf("\n");

    system("pause");
    return 1;
}

测试结果:

题目二:实现一个函数:一个楼梯有50个台阶,每一步可以走一个台阶,也可以走两个台阶,请问走完这个楼梯共有多少种方法?

分析:

1步台阶只有1种走法(1)

2步台阶2种(11、2)

3步台阶有3种(111、12、21)

4步台阶有5种(1111、112、121、211、22)

5步台阶有8种(11111、1112、1121、1211、122、2111、212、221)

6步台阶有13种(111111、11112、11121、11211、1122、12111,1212、1221、2111、2112、2121、2211、222)

..............

假设走完k个台阶有f(k)种走法。

k = 1时,f(k) = 1

k = 2时,f(k) = 2

k = n时,第一步走一个台阶,剩n-1个台阶,有f(n - 1)种走法。第一步走两个台阶,剩n-2个台阶,有f(n - 2)种走法。所以共有f(n - 1) + f(n - 2)种走法。

于是有如下公式:

显然此题与上题类似!