• 实现斐波那契数列逐步降维打击


    斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:

    F(0) = 0,F(1) = 1
    F(n) = F(n - 1) + F(n - 2),其中 n > 1
    给你 n ,请计算 F(n) 。

    示例 1:
    
    输入:2
    输出:1
    解释:F(2) = F(1) + F(0) = 1 + 0 = 1
    示例 2:
    
    输入:3
    输出:2
    解释:F(3) = F(2) + F(1) = 1 + 1 = 2
    示例 3:
    
    

    0 <= n <= 30来源:力扣(LeetCode)

    链接:https://leetcode-cn.com/problems/fibonacci-number
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    解法一:直接“傻递归”

    为什么叫傻递归,最大原因是存在大量大量的重复计算。详细请自己画画递归树,自己推一推。

    自顶向上,存在大量重复的计算

    分析:

    ​ 1. 时间复杂度: O(2^n)

    /**
     * @param {number} n
     * @return {number}
     */
    var fib = function(n) {
        if (n === 0 || n === 1) return n;
        if (n === 2) return 1;
        return fib(n-1) + fib(n-2);
    };
    

    解法二:聪明递归

    针对以上的傻递归,设置一个数组memo或者哈希表来存储中间结果,计算的时候看是否在memo中含有结果,如果有的话就直接返回

    事件复杂度: 0(n)

    空降复杂度:0(n) 空间换时间的一个案例

    /**
     * @param {number} n
     * @return {number}
     */
    var fib = function(n) {
    	const memo = [];
      return helper(memo,n);
    };
    function helper(memo,n) {
      if (n === 1 || n === 0) return n;
      if (n === 2) return 1;
      // 先查表
      if (memo[n]) return memo[n];
      memo[n] = helper(memo,n-1) + helper(memo,n-2);
      return memo[n];
    }
    

    方法三:使用动态规划

    f(0) = 0 f(1) = 1 f(2) = 1 f(n) = f(n-1) + f(n-1);

    时间复杂度: 0(n)

    空间复杂度: 0(n)

    /**
     * @param {number} n
     * @return {number}
     */
    var fib = function(n) {
      	const memo = [];
      	memo[0] = 0;
      	memo[1] = 1;
      	memo[2] = 1;
      	for(let i = 3; i <= n; ++i) {
          memo[i] = memo[i-1] + memo[i-2];
        }
      return memo[n];
    };
    

    方法四:压缩状态

    由状态方程可以知道,结果只有两个状态有关,即 n-1和n-2

    时间复杂度: 0(n)

    空间复杂度:0(n)

    /**
     * @param {number} n
     * @return {number}
     */
    var fib = function(n) {
        let first = 0,second = 1,result;
        if (n === 0 || n === 1) return n;
        for(let i = 2; i <= n; ++i) {
            result = first + second;
            first = second;
            second = result;
        }
        return result;
    };
    

    总结

    ​ 斐波那契问题是动态规划的一个很好的切入点,但是它还不是动态规划的问题,因为它没有求最值的要求。

    但是我们可以学习的是,第一找到状态转义方程,然后进行傻递归,然后设置备忘录去进行一个优化递归,然后进行一个动态规划的思路,最后去进行动态规划的优化。方法一到方法四十完全是沿着这条路一直走下来的。一步一步实现降为打击。官方题解中还有两种较为高级的解法,对数学要求相当的高,可以去看看!

    参考

    • 《labuladong的算法小抄》

    • leetcode官方题解

    慢慢来,比较快!基础要牢,根基要稳!向大佬致敬!
  • 相关阅读:
    Android开发——弹性滑动的两种实现方式
    管理知识和解决信息爆炸问题的4种方法
    京东金融的业务版图
    京东金融的业务版图
    虚幻引擎4艺术大师
    Android开发——View滑动的三种实现方式
    Android开发之Path类使用详解,自绘各种各样的图形!
    C# Dictionary的遍历理解
    我想走全产业链发展路线
    Androd安全——混淆技术完全解析
  • 原文地址:https://www.cnblogs.com/rookie123/p/14651182.html
Copyright © 2020-2023  润新知