☮斐波那契数列与动态规划

简介: ☮斐波那契数列与动态规划

一、斐波那契数列


斐波那契数列 又称兔子数列,它有这样的公式: Fn = Fn-1 + Fn-2。换句话说,下一个数字是前两个数字的和。


前两个数是1,然后是2(1+1),3(2+1),5(2+3),813...


现在有一个需求是编写一个函数fib(n)返回第n个斐波那契数。


在编写函数之前,还想让大家了解一下动态规划的知识。


二、动态规划中的自顶向下和自底向上


image.png


图片来自书籍 算法导论 第15章动态规划。


三、两种思想在斐波那契数列数列问题种的体现


1. 自顶向下的思想(递归)


function fib(n){
    if (n <= 1) {
        return n
    }
    return fib(n - 1) + fib(n - 2)
}
// 三目简洁版
function fib(n) {
    return n <= 1 ? n : fib(n - 1) + fib(n - 2)
}
复制代码


很显然使用递归能完成需求,但是n较大时会变得很慢,调用该函数会挂起引擎一段时间,消耗所有CPU资源,测试结果可见下图,小伙伴们自己测试时千万不要将n设置的很大,否则你的该页面可能会崩溃的😅。


image.png


why? 为什么会这么慢?我们简单的画出递归树,就知道是为啥了👻


image.png


图片参考自现代JavaScript教程-递归和堆栈


我们可以清楚的看到 fib(3) 被计算了两次,fib(2) 被计算了三次。总计算量远远超过了 n,这造成仅仅对于计算 n=40 来讲,计算量就是巨量的。n越大,计算量就越大。


我们还可以选择不使用递归的解法👇🏿。


2. 自底向上的思想(循环)


function fib(n) { 
    let a = 1
    let b = 1
    for (let i = 3; i <= n; i++) { 
        let c = a + b
        a = b
        b = c
    } return b
}
// 可视化序列
a  b  c 
1, 1, 2
   a  b  c 
1, 1, 2, 3
      a  b  c 
1, 1, 2, 3, 5
         a  b  c 
1, 1, 2, 3, 5, 8
复制代码


该解法的思想就是动态规划种的自底向上,依次类推,直到我们得到需要的值,这比递归快得多,该解法的时间复杂度为O(n),而递归解法的时间复杂度为O(n^2)


四、总结


虽然递归有时解决问题很容易,但是还是要考虑算法的性能,是否出现过多重复的计算,如果出现过多重复的计算,那么这条路一定不是最正确的解法。


两种方法方法得到的算法具有相同的渐进运行时间,仅有的差异是在某些特殊情况下,自顶向下方法并未真正递归地考察所有可能的子问题。由于没有频繁的递归函数调用的开销,自顶向上的时间复杂性函数通常具有更小的系数。

相关文章
|
8月前
|
算法 C++
【动态规划】斐波那契数列模型(C++)
【动态规划】斐波那契数列模型(C++)
|
4月前
动态规划——斐波那契模型
本文介绍了动态规划的基本步骤及其在几个典型问题中的应用。首先概述了动态规划的四个关键步骤:状态表示、状态转移方程、初始化及填表顺序,并说明了如何确定返回值。接着通过具体实例讲解了第 N 个泰波那契数、三步问题、使用最小花费爬楼梯以及解码方法等问题的求解过程,详细阐述了每一步的具体实现方法与代码示例。最后还讨论了如何优化初始化过程以简化编码。
43 4
动态规划——斐波那契模型
|
8月前
|
算法
【超直白】算法:斐波那契数列
【超直白】算法:斐波那契数列
【超直白】算法:斐波那契数列
|
8月前
|
算法 Java 测试技术
斐波那契数列的四种实现算法
斐波那契数列的四种实现算法
182 3
|
8月前
|
存储 算法
精益求精——斐波那契数列的logn解法
精益求精——斐波那契数列的logn解法
117 0
动态规划| 【斐波那契数列模型 】|1137.第N个泰波那锲数
动态规划| 【斐波那契数列模型 】|1137.第N个泰波那锲数
|
9月前
|
算法
算法修炼-动态规划之斐波那契数列模型
算法修炼-动态规划之斐波那契数列模型
|
前端开发 程序员 测试技术
斐波那契数列的多种解法
斐波那契数列的多种解法
斐波那契数列的多种解法
|
算法
30.斐波那契数列
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。 n<=39
85 0
30.斐波那契数列