每日一道剑指offer-斐波那契数列

本文介绍了三种计算斐波那契数列第n项的方法:迭代法、递归法和动态规划法。针对递归法的效率问题,动态规划法通过保存中间结果避免了重复计算,提高了效率。所有方法均考虑了结果取模1e9+7的需求,适用于0≤n≤100的范围。
摘要由CSDN通过智能技术生成

题目:

写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:

F(0) = 0,   F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。

答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

示例 1:

输入:n = 2
输出:1

示例 2:

输入:n = 5
输出:5

提示:

  • 0 <= n <= 100

解析:

这道题应该很多人都做过,刚开始学编程都会遇到这道题,这道题跟爬楼梯,青蛙跳台阶特别相似,不过就是初始条件的不同罢了。这道题有三种方法可以解决,最常用的传统方法-迭代法,根据这个数列的规律去解决,其次是使用递归来解决,在递归的基础上,用动态规划的方,解决递归重复计算的问题。

第一种:迭代法,根据斐波那契数列的规律,从第3项开始,每一个项都等于前两项的和,然后进行遍历相加赋值即可。

# 第一种,根据斐波那契数列的规律,直接遍历返回即可。(这是从小到大,自底向上)(迭代法)
def fib(n: int) -> int:
    f0 = 0
    f1 = 1
    while n > 0:
        # f0代表前一项,f1代表后一项(后一项总是等于前两项的和)
        f0, f1 = f1, f0 + f1  # 因为fib数列除了1,2项之外,之后都是前两项的和,所以每次遍历,都将新的结果赋值给之前。
        # 保留最新项的结果,最后返回要获取的第几项结果
        n -= 1
    return f0 % int(1e9 + 7)

 

第二种:采用递归的方法,自顶向下,从当前数一直递归到终止条件,然后回溯相加即可。

#第二种,递归(自顶向下,然后回溯即可):有两个终止条件,n==0,f0=0,n==1,f1=1
def fib2(n: int) -> int:
    if n==0:
        f0 = 0
        return f0
    elif n==1:
        f1 = 1
        return f1
    # 递归条件:F(N) = F(N - 1) + F(N - 2):
    # 把 f(n)问题的计算拆分成 f(n-1)和 f(n-2)两个子问题的计算,并递归,
    # 以 f(0)和 f(1)为终止条件。
    return (fib2(n-1)+fib2(n-2))%int(1e9 + 7)

 

第三种方法:动态规划法,因为递归进行了重复计算,在递归的过程中,其中的某一项需要计算多次(例如 f(n) 和 f(n - 1) 两者向下递归需要各自计算 f(n - 2)的值。)那么我们可以将中间结果保存起来,当再次计算时只需要拿出来即可。

#第三种,动态规划:以斐波那契数列性质 f(n + 1) = f(n) + f(n - 1)为转移方程。(爬楼梯翻版)
#解决了递归大量重复的计算
def fib3(n: int) -> int:
    dp = [0]*(n+1) #动态规划网格
    if n==0:
        return 0
    #动态规划初始条件
    dp[0] = 0
    dp[1] = 1
    for i in range(2,n+1):
        dp[i] = dp[i-1]+dp[i-2] #状态转移方程
    return dp[-1] #返回最终的结果

执行结果:

输入10

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值