• LeetCode 斐波那契数算法题解 All In One


    LeetCode 斐波那契数算法题解 All In One

    1. Fibonacci Number

    2. 斐波那契数

    The Fibonacci numbers, commonly denoted F(n) form a sequence, called the Fibonacci sequence, such that each number is the sum of the two preceding ones, starting from 0 and 1. That is,

    斐波那契数,通常表示为 F(n) 形成一个序列,称为斐波那契数列,使得每个数都是前两个数的和,从 0 和 1 开始。也就是说,

    F(0) = 0, F(1) = 1
    F(n) = F(n - 1) + F(n - 2), for n > 1.
    
    

    https://www.shuxuele.com/numbers/fibonacci-sequence.html

    https://r-knott.surrey.ac.uk/Fibonacci/fibtable.html

    最佳实践

    性能优化

    ES6 尾递归调用优化 性能优化

    尾调用

    // ES6 尾递归调用优化 性能优化
    
    function Fibonacci(n, n1 = 1, n2 = 1) {
        if (n < 2) {
            return n;
        }
        if (n === 2) {
            //  ✅ n2  ???
            return n2;
        }
        return Fibonacci(n - 1, n2, n1 + n2);
    }
    
    // 0 <= n <=  30
    
    function Fibonacci(n, n1 = 1, n2 = 1) {
        if (n < 2) {
            return n;
        }
        if (n === 2) {
            return 1; ❌
        }
        return Fibonacci(n - 1, n2, n1 + n2);
    }
    
    function Fibonacci(n, n1 = 1, n2 = 1) {
        if (n === 0) {
            return 0;
        }
        if (n <= 2) {
            return 1; ❌
        }
        return Fibonacci(n - 1, n2, n1 + n2);
    }
    
    /*
    
    Fibonacci(0)
    0
    Fibonacci(1)
    1
    Fibonacci(2)
    1
    Fibonacci(3)
    2
    Fibonacci(5)
    5
    Fibonacci(30)
    832040
    Fibonacci(100)
    354224848179262000000
    
    */
    
    
    // ❌ Parameter cannot have question mark and initializer.ts(1015)
    // function fibnacci(n: number, n1?: number = 1, n2?: number = 1): number {
    //   if (n < 2) {
    //     return n;
    //   }
    //   if (n === 2) {
    //     // ✅ new n2 = n1 + n2
    //     return n2;
    //   }
    //   return fibnacci(n - 1, n2, n1 + n2);
    // }
    
    
    // ES6 尾递归调用优化 性能优化
    function fibnacci(n: number, n1: number = 1, n2: number = 1): number {
      if (n < 2) {
        return n;
      }
      if (n === 2) {
        // ✅ new n2 = n1 + n2
        return n2;
      }
      return fibnacci(n - 1, n2, n1 + n2);
    }
    
    
    
    "use strict";
    
    /**
     *
     * @author xgqfrms
     * @license MIT
     * @copyright xgqfrms
     * @created 2022-09-30
     * @modified
     *
     * @description 509. Fibonacci Number
     * @description 509. 斐波那契数
     * @difficulty Easy
     * @time_complexity O(n)
     * @space_complexity O(n)
     * @augments
     * @example
     * @link https://leetcode.com/problems/fibonacci-number/
     * @link https://leetcode.cn/problems/fibonacci-number/
     * @solutions
     *
     * @best_solutions
     *
     * @refs
     *
     *
     */
    
    // export {};
    
    const log = console.log;
    
    // function fib(n: number): number {
    //   if(n === 0) {
    //     return 0;
    //   }
    //   if(n === 1 || n === 2) {
    //     return 1;
    //   }
    //   let n1 = 1;
    //   let n2 = 1;
    //   while (n > 2) {
    //     // ES6 swap
    //     [n1, n2] = [n2, (n1 + n2)];
    //     // ES5 swap
    //     // const temp = n1 + n2;
    //     // n1 = n2;
    //     // n2 = temp;
    //     n -= 1;
    //   }
    //   return n2;
    // }
    
    
    function fib(n: number): number {
      if(n === 0) {
        return 0;
      }
      let n1 = 1;
      let n2 = 1;
      // while loop
      while (n > 2) {
        // ES6 swap
        [n1, n2] = [n2, (n1 + n2)];
        n -= 1;
      }
      return n2;
    }
    
    // function fib(n: number): number {
    //   if(n === 0) {
    //     return 0;
    //   }
    //   let n1 = 1;
    //   let n2 = 1;
    //   // for loop
    //   for (let i = 2; i < n; i++) {
    //     // ES6 swap
    //     [n1, n2] = [n2, (n1 + n2)];
    //   }
    //   return n2;
    // }
    
    
    // 测试用例 test cases
    const testCases = [
      {
        input: 0,
        result: 0,
        desc: 'value equal to 0',
      },
      {
        input: 1,
        result: 1,
        desc: 'value equal to 1',
      },
      {
        input: 2,
        result: 1,
        desc: 'value equal to 1',
      },
      {
        input: 5,
        result: 5,
        desc: 'value equal to 5',
      },
      {
        input: 8,
        result: 21,
        desc: 'value equal to 21',
      },
      // leetcode 509: 0 <= n <= 30
      {
        input: 30,
        result: 832040,
        desc: 'value equal to 832040',
      },
      {
        input: 32,
        result: 2178309,
        desc: 'value equal to 2178309',
      },
      {
        input: 64,
        result: 10610209857723,
        desc: 'value equal to 10610209857723',
      },
      {
        input: 80,
        result: 23416728348467685,
        desc: 'value equal to 23416728348467685',
      },
      {
        input: 90,
        result: 2880067194370816120,
        desc: 'value equal to 2880067194370816120',
      },
      // {
      //   input: 100,
      //   result: 354224848179261915075,
      //   desc: 'value equal to 354224848179261915075',
      // },
    ];
    
    log(`fib(80) ??? 23416728348467685 => 23416728348467684 =`, 23416728348467685 === 23416728348467684);
    // fib(90) ??? 2880067194370816120 => 2880067194370816000 = true
    
    log(`fib(90) ??? 2880067194370816120 => 2880067194370816000 =`, 2880067194370816000 === 2880067194370816120);
    // fib(90) ??? 2880067194370816120 => 2880067194370816000 = true
    
    // ❌ error TS2367: This condition will always return 'false' since the types '354224848179261900000' and '354224848179262000000' have no overlap.
    // log(`fib(100) 超出最大范围了 ❌ 354224848179261915075 => 354224848179262000000 =`, 354224848179261915075 === 354224848179262000000, `❌\n`);
    // fib(100) 超出最大范围了 ❌ 354224848179261915075 => 354224848179262000000 = false
    
    // 超出最大范围了 ❌
    // fib(100) => 354224848179261915075 Math (https://r-knott.surrey.ac.uk/Fibonacci/fibtable.html)
    // fib(100) => 354224848179262000000 Chrome ❌
    // fib(100) => 354224848179262000000 Node.js ❌
    
    // $ npx ts-node ./509\ fibonacci-number.ts
    
    for (const [i, testCase] of testCases.entries()) {
      const result = fib(testCase.input);
      // log(`test case ${i} result: `, result === testCase.result ? `✅ passed` : `❌ failed result = ${result}`, testCase.result);
      log(`test case ${i} result: `, result === testCase.result ? `✅ passed fib(${testCase.input})'s =` : `❌ failed`, result);
      if(testCase.input === 30) {
        log(`⚠️ fib(n), n max is 30\n`);
      }
    }
    
    // const testCases = [...new Uint8Array(100)].map((item, i) => ({
    //   input: i,
    //   result: fib(i),
    //   desc: `value equal to ${fib(i)}`,
    // }));
    // ...spread 突破, 2**8 = 256 的 number 最大值的大小限制 ✅
    // const testCases = [...new Uint8Array(100)].map((item, i) => i + 1);
    // for (const [i, testCase] of testCases.entries()) {
    //   const result = fib(testCase);
    //   log(` test case ${i} result = `, result);
    // }
    
    // export {}
    
    /*
    
    $ npx ts-node ./fib.ts
    $ npx ts-node ./509\ fibonacci-number.ts
    
    fib(80) ??? 23416728348467685 => 23416728348467684 = true
    fib(90) ??? 2880067194370816120 => 2880067194370816000 = true
    fib(100) 超出最大范围了 ❌ 354224848179261915075 => 354224848179262000000 = false ❌
    
    test case 0 result:  ✅ passed 0
    test case 1 result:  ✅ passed 1
    test case 2 result:  ✅ passed 1
    test case 3 result:  ✅ passed 5
    test case 4 result:  ✅ passed 21
    test case 5 result:  ✅ passed 2178309
    test case 6 result:  ✅ passed 10610209857723
    test case 7 result:  ✅ passed 23416728348467684
    test case 8 result:  ✅ passed 2880067194370816000
    
    
    */
    
    
    
    
    "use strict";
    
    /**
     *
     * @author xgqfrms
     * @license MIT
     * @copyright xgqfrms
     * @created 2022-09-30
     * @modified
     *
     * @description 509. Fibonacci Number
     * @description 509. 斐波那契数
     * @difficulty Easy
     * @time_complexity O(n)
     * @space_complexity O(n)
     * @augments
     * @example
     * @link https://leetcode.com/problems/fibonacci-number/
     * @link https://leetcode.cn/problems/fibonacci-number/
     * @solutions
     *
     * @best_solutions
     *
     * @refs 
     *
     *
     */
    
    const log = console.log;
    
    function fib(n) {
      if(n === 0) {
        return 0;
      }
      if(n === 1 || n === 2) {
        return 1;
      }
      let n1 = 1;
      let n2 = 1;
      while (n > 2) {
        // ES6 swap
        [n1, n2] = [n2, (n1 + n2)];
        // ES5 swap
        // const temp = n1 + n2;
        // n1 = n2;
        // n2 = temp;
        n -= 1;
      }
      return n2;
    }
    
    // 测试用例 test cases
    const testCases = [
      {
        input: 0,
        result: 0,
        desc: 'value equal to 0',
      },
      {
        input: 1,
        result: 1,
        desc: 'value equal to 1',
      },
      {
        input: 2,
        result: 1,
        desc: 'value equal to 1',
      },
      {
        input: 5,
        result: 5,
        desc: 'value equal to 5',
      },
      {
        input: 8,
        result: 21,
        desc: 'value equal to 21',
      },
      {
        input: 32,
        result: 2178309,
        desc: 'value equal to 2178309',
      },
      {
        input: 64,
        result: 10610209857723,
        desc: 'value equal to 10610209857723',
      },
      {
        input: 80,
        result: 23416728348467685,
        desc: 'value equal to 23416728348467685',
      },
      {
        input: 90,
        result: 2880067194370816120,
        desc: 'value equal to 2880067194370816120',
      },
      // {
      //   input: 100,
      //   result: 354224848179261915075,
      //   desc: 'value equal to 354224848179261915075',
      // },
    ];
    
    log(`fib(80) ??? 23416728348467685 => 23416728348467684 =`, 23416728348467685 === 23416728348467684);
    // fib(90) ??? 2880067194370816120 => 2880067194370816000 = true
    
    log(`fib(90) ??? 2880067194370816120 => 2880067194370816000 =`, 2880067194370816000 === 2880067194370816120);
    // fib(90) ??? 2880067194370816120 => 2880067194370816000 = true
    
    log(`fib(100) 超出最大范围了 ❌ 354224848179261915075 => 354224848179262000000 =`, 354224848179261915075 === 354224848179262000000, `❌\n`);
    // fib(100) 超出最大范围了 ❌ 354224848179261915075 => 354224848179262000000 = false
    
    // 超出最大范围了 ❌
    // fib(100) => 354224848179261915075 Math (https://r-knott.surrey.ac.uk/Fibonacci/fibtable.html)
    // fib(100) => 354224848179262000000 Chrome ❌
    // fib(100) => 354224848179262000000 Node.js ❌
    
    // $node ./fib.js
    
    for (const [i, testCase] of testCases.entries()) {
      const result = fib(testCase.input);
      // log(`test case ${i} result: `, result === testCase.result ? `✅ passed` : `❌ failed result = ${result}`, testCase.result);
      log(`test case ${i} result: `, result === testCase.result ? `✅ passed` : `❌ failed`, result);
    }
    
    // const testCases = [...new Uint8Array(100)].map((item, i) => ({
    //   input: i,
    //   result: fib(i),
    //   desc: `value equal to ${fib(i)}`,
    // }));
    // ...spread 突破, 2**8 = 256 的 number 最大值的大小限制 ✅
    // const testCases = [...new Uint8Array(100)].map((item, i) => i + 1);
    // for (const [i, testCase] of testCases.entries()) {
    //   const result = fib(testCase);
    //   log(` test case ${i} result = `, result);
    // }
    
    // export {}
    
    /*
    
    $ node ./fib.js
    
    fib(80) ??? 23416728348467685 => 23416728348467684 = true
    fib(90) ??? 2880067194370816120 => 2880067194370816000 = true
    fib(100) 超出最大范围了 ❌ 354224848179261915075 => 354224848179262000000 = false ❌
    
    test case 0 result:  ✅ passed 0
    test case 1 result:  ✅ passed 1
    test case 2 result:  ✅ passed 1
    test case 3 result:  ✅ passed 5
    test case 4 result:  ✅ passed 21
    test case 5 result:  ✅ passed 2178309
    test case 6 result:  ✅ passed 10610209857723
    test case 7 result:  ✅ passed 23416728348467684
    test case 8 result:  ✅ passed 2880067194370816000
    
    
    */
    
    
    

    https://leetcode.com/problems/fibonacci-number/

    https://leetcode.cn/problems/fibonacci-number/

    demos

    "use strict";
    
    /**
     *
     * @author xgqfrms
     * @license MIT
     * @copyright xgqfrms
     * @created 2022-06-12
     * @modified
     *
     * @description 509. Fibonacci Number
     * @description 509. 斐波那契数
     * @difficulty Easy
     * @complexity O(n)
     * @time O(n)
     * @augments
     * @example
     * @link https://leetcode.com/problems/fibonacci-number/
     * @link https://leetcode.cn/problems/fibonacci-number/
     * @solutions
     * @refs 
     *
     * @best_solutions
     *
     */
    
    const log = console.log;
    
    
    /**
     * @param {number} n
     * @return {number}
     */
    var fib = function(n) {
      if(n <= 1) {
        return n;
      }
      // 递归
      return fib(n - 1) + fib(n - 2);
    };
    
    
    // DP 动态规划, 缓存
    
    var fib = function(n) {
      const cache = [0, 1];
      function getCache(n) {
        if(!cache.includes(n)) {
          cache[n] = getCache(n - 1) +  getCache(n - 2);
        }
        return cache[n];
      }
      return getCache(n);
    };
    
    
    // 性能优化, 滑动数组 ✅
    var fib = function(n) {
      if(n <= 1) {
        return n;
      }
      const arr = [0, 1];
      let sum;
      for (let i = 2; i <= n; i++) {
        // 前面两个元素的和
        sum = arr[0] + arr[1];
        arr[0] = arr[1];
        arr[1] = sum;
      }
      return sum;
    };
    
    // var fib = function(n) {
    //   const arr = [0, 1];
    //   if(n <= 1) {
    //     return arr[n];
    //   }
    //   let sum;
    //   for (let i = 2; i <= n; i++) {
    //     // 前面两个元素的和
    //     sum = arr[0] + arr[1];
    //     arr[0] = arr[1];
    //     arr[1] = sum;
    //   }
    //   return sum;
    // };
    
    // 性能优化, 变量 swap
    var fib = function(n) {
      let first = 0;
      let second = 1;
      if(n <= 1) {
        return n;
      }
      let sum;
      for (let i = 2; i <= n; i++) {
        // 前面两个元素的和
        sum = first + second;
        first = second;
        second = sum;
      }
      return sum;
    };
    
    
    // 动态数组,空间换时间
    
    const arr = [0, 1];
    var fib = function(n) {
      if(n <= 1) {
        return n;
      }
      for (let i = 2; i <= n; i++) {
        // 前面两个元素的和
        arr[i] = arr[i - 1] + arr[i - 2];
      }
      return arr[i];
    };
    
    (() => {
      const arr = [0, 1];
      var fib = function(n) {
        for (let i = 2; i <= n; i++) {
          // 前面两个元素的和
          arr[i] = arr[n - 1] + arr[n - 2];
        }
        return arr[i];
      };
    })();
    
    
    
    

    refs

    https://zzk.cnblogs.com/my/s/blogpost-p?Keywords=fib

    https://www.cnblogs.com/xgqfrms/tag/fibonacci/

    尾递归/尾调用

    tail recursion

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions#recursion

    Recursion is limited by stack size

    递归受堆栈大小限制

    https://developer.mozilla.org/en-US/docs/Glossary/Recursion

    DP / 动态规划

    https://xiaochen1024.com/series/6196129fc1553b002e57bef5/619621d3c1553b002e57bef8



    ©xgqfrms 2012-2020

    www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

    原创文章,版权所有©️xgqfrms, 禁止转载 ️,侵权必究⚠️!


  • 相关阅读:
    Objective--C三大特性:封装,继承,多态(零碎笔记)
    零碎的知识点
    Objective--C之《文件操作》练习代码
    Objective--C的Foundation frame之NSMutableDictionary代码
    Objective--C的Foundation frame之NSMutableArray代码
    Objective--C随笔2016年8月7日
    关于OC中的委托delegate
    javascript 绝对路径工具类
    IE 弹出框处理经验
    InputStream和OutputStream 何时使用
  • 原文地址:https://www.cnblogs.com/xgqfrms/p/16748194.html
Copyright © 2020-2023  润新知