剑指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(n1)+f(n2) 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的大矩形,总共有多少种方法?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值