xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

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, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2022-10-02 08:43  xgqfrms  阅读(41)  评论(2编辑  收藏  举报