js生成斐波那契数列的几种写法总结
1. 使用generator函数和for of循环实现斐波那契数列;
1 // 使用generator函数和for of循环实现斐波那契数列; 2 /** 3 * @function fibNumbers 4 * @description 生成斐波那契数列的函数 5 * @param {number} num 表示要生成最大数不超过num的斐波那契数列 6 * @return 返回值一个斐波那契数列的数组 7 */ 8 function fibNumbers(num) { 9 function* fibonacci() { 10 let [prev, curr] = [0, 1]; 11 for (;;) { 12 yield curr; 13 [prev, curr] = [curr, prev + curr]; 14 } 15 } 16 const numbers = []; 17 for (let n of fibonacci()) { 18 if (n > num) break; 19 // console.log(n); 20 numbers.push(n); 21 } 22 return numbers; 23 } 24 const fibonacciArr = fibNumbers(50); 25 // 输出: [1, 1, 2, 3, 5, 8, 13, 21, 34]
2. 使用递归和for循环求第n个斐波那契数:
1 // 计算第n个斐波那契数是多少的函数 2 // 1.for循环方式,速度最快 3 function fibonacciByFor(n) { 4 if (n === 1 || n === 2) { 5 return 1; 6 } 7 let [pre, cur] = [1, 1]; 8 // 如果是以下标计算,for循环中第二个语句为 (i <= n;) 9 for(let i = 2;i < n;i++){ 10 // 1.1 一般的写法, 执行耗时最短 11 const sum = pre + cur; 12 pre = cur; 13 cur = sum; 14 // 1.2 解构赋值的写法 15 // [pre, cur] = [cur, pre + cur]; 16 } 17 // console.log(`第${n}个斐波那契数为:`, cur); 18 return cur; 19 } 20 console.time('for循环斐波那契'); 21 fibonacciByFor(20); // 输出:6765, 耗时:0.06689453125 ms 22 console.timeEnd('for循环斐波那契'); 23 24 // 2.递归方式,性能没有for循环好 25 // 2.1 普通递归 26 // 如果n为5,则会重复计算fibByRecursion(4)两次 27 // n越大则重复计算的次数越多, 28 // 这样会导致堆栈溢出, 浏览器出现假死状态,导致无法及时计算出结果(当值设置为50的时候就很明显了) 29 function fibByRecursion(n) { 30 if (n === 1 || n === 2) { 31 return 1; 32 } 33 return fibByRecursion(n - 2) + fibByRecursion(n - 1); 34 } 35 console.time('普通递归'); 36 fibByRecursion(20); // 输出:6765, 耗时:1.19287109375 ms 37 console.timeEnd('普通递归'); 38 39 // 2.2 递归改进1,避免重复计算 40 function fibByRecursion1(n) { 41 // 把前后两位数作为参数,在传递参数时进行计算 42 return fib(n, 1, 1); 43 function fib(n, pre, cur) { 44 if (n === 1) { 45 return pre; 46 } 47 if (n === 2) { 48 return cur; 49 } 50 return fib(n - 1, cur, pre + cur); 51 } 52 } 53 console.time('递归改进1'); 54 fibByRecursion1(20); // 输出:6765, 耗时:0.0888671875 ms 55 console.timeEnd('递归改进1'); 56 57 // 2.3 递归改进2,使用闭包的作用域特性把计算的结果存储在数组中,避免了重复计算 58 function fibByRecursion2(n) { 59 let initMembers = [0, 1]; 60 return fib(n); 61 function fib(n) { 62 if (initMembers[n] === undefined) { 63 // 把不存在的项存到数组中,下次再找到当前存储的第n项时就不会重新计算了 64 initMembers[n] = fib(n - 2) + fib(n - 1); 65 } 66 return initMembers[n]; 67 } 68 } 69 console.time('递归改进2'); 70 fibByRecursion2(20); // 输出:6765, 耗时:0.091796875 ms 71 console.timeEnd('递归改进2'); 72 73 // 2.4 递归改进3,提取fibByRecursion2中的存储计算结果的功能函数 74 function fibByRecursion3(n) { 75 let fib = setMemory(function (n) { 76 if (n === 1 || n === 2) { 77 return 1; 78 } 79 return fib(n - 2) + fib(n - 1); 80 }); 81 return fib(n); 82 // 将存储功能提取到一个函数中 83 function setMemory(fn) { 84 let memorizer = []; 85 return function (n) { 86 if (memorizer[n] === undefined) { 87 memorizer[n] = fn(n); 88 } 89 return memorizer[n]; 90 } 91 } 92 } 93 console.time('递归改进3'); 94 fibByRecursion3(20); // 输出:6765, 耗时:0.092041015625 ms 95 console.timeEnd('递归改进3');
3. 参考链接: