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. 参考链接:

3.1 JS写斐波那契数列的几种方法;

3.2【java】递归次数过多导致堆栈溢出;

 

posted @ 2021-09-18 16:31  CooperGao  阅读(246)  评论(0编辑  收藏  举报