关于javascript:JavaScript-实现输出斐波那契数列

25次阅读

共计 2511 个字符,预计需要花费 7 分钟才能阅读完成。

问渠那得清如许,为有源头活水来。

想要放弃本人的技术生机,最无效的伎俩就是通过一直地输出来提供足够的营养。咱们也不用刻意追求浅近的或者陈腐的知识点,通过对一个根底问题的全方位多维度解析,同样也会播种不小。

题目

有这么一道题目须要咱们来解答:

  • 试输入斐波那契数列的前 10 项,即 1、1、2、3、5、8、13、21、34、55。

剖析

有些人看到题目中呈现了“斐波那契数列”这个概念后,可能脑袋就蒙圈了,其实大可不必!

对于这道题,能够不必理睬这个生疏概念,咱们只须要关怀前面它给出的数字法则即可。

咱们能够看到,法则总结起来就一句话:从第三位开始,前面每项的值等于前两项之和,用式子示意的话就是:a~n~ = a~n-1~ + a~n-2~(n ≥ 2)。

依据题目要求,其实就是要咱们做两件事:

  1. 生成每一项的值。
  2. 打印输出所有值。

根底解法

解题思路:

  • 创立一个数组寄存数列各项的值。
  • for 循环生成数列各项并存入数组(为了计算前面各项的值),打印生成的项。

代码实现如下:

/**
 * @description 创立一个生成数列数组的办法
 * @param {number} n 示意要生成多少项(即数组长度,不是数组下标)*/
function createFibArr(n) {
    // 申明一个存放数据的数组
    let fibArr = [];
    // 从第三项 (下标为 2) 开始,每一项都等于前两项之和
    for (let index = 0; index < n; index++) {index < 2 ? fibArr.push(1) : fibArr.push(fibArr[index - 1] + fibArr[index - 2]);
        console.log(fibArr[index]);
    }
}

// 调用办法
createFibArr(10);

剖析:

这应该是最根本的解题办法,很容易就实现了。

但如果这是面试题的话,这样的答案只能说是中规中矩,没有出彩的中央,最重要的是体现不出咱们不同凡响的气质啊,所以,咱们应该用点其余的伎俩来晋升下本人的逼格!

高级递归

解题思路:

  • 通过递归的伎俩计算出各地位对应的值(这里有个前提是:第一项和第二项是确定值,否则,递归就不好用了)。
  • 打印后果。

代码实现如下:

/**
 * @description 计算出第 n 项的值
 * @param {number} n 示意每一项的下标值
 * @returns {number} 下标为 n 的地位的值 
 */
function calFibValue(n) {console.count("执行次数:")
    return n < 2 ? 1 : (calFibValue(n - 1) + calFibValue(n - 2));
}

/**
 * @description 打印计算结果
 * @param {number} n 代表要打印多少项
 */
function printRes(n) {for (let index = 0; index < n; index++) {console.log(calFibValue(index));
    }
}

// 调用打印办法
printRes(10);

// 执行次数:: 276

剖析:

递归的应用的确晋升了代码的逼格,然而又引来了另外一个问题:性能问题。

每一项的值都是从第一项开始计算累加 进去的,比方计算第四项的值,其过程如下:

  1. 返回第一项的值:1。
  2. 返回第二项的值:1。
  3. 计算第三项的值为 1 + 1 = 2。
  4. 计算第四项的值为 2 + 1 = 3。

在计算第五项值的时候,还要通过下面这个过程来获取第四项的值,进行了大量的反复运算。

为了惊艳面试官,咱们还须要再做优化!

递归优化

解题思路:

  • 导致反复计算的是递归那局部的逻辑,所以优化点在递归这里。
  • 既然存在反复运算,那就意味着其实前面的运算齐全能够应用后面曾经计算出来的值,所以咱们须要引入缓存来保留每次的计算结果。

代码实现:

/**
 * @description 计算出第 n 项的值
 * @param {number} n 示意每一项的下标值
 * @returns {number} 下标为 n 的地位的值 
 */

// 寄存每次计算结果的 Map 构造
// 这里也能够用数组,然而在语义方面没有 Map 或对象间接
let fibValueMap = new Map();
function calFibValue(n) {console.count("执行次数:");
    // 如果缓存中已存在对应的值,则间接返回
    if (fibValueMap.has(n)) {return fibValueMap.get(n);
    }
    const value = n < 2 ? 1 : (calFibValue(n - 1) + calFibValue(n - 2));
    // 在计算出每一项的之后,须要及时存入 Map
    fibValueMap.set(n, value);
    return value;
}

/**
 * @description 打印计算结果
 * @param {number} n 代表要打印多少项
 */
function printRes(n) {for (let index = 0; index < n; index++) {console.log(calFibValue(index));
    }
}

// 调用打印办法
printRes(10);

// 执行次数:: 26

剖析:

依据打印进去的 count 来看,优化后的递归次数是优化前的 1/10 左右,这个后果就很惊喜了。

这次面试官应该能够称心了吧。

总结

万变不离其宗,只有将解题思路理清了,代码实现只是一个后果而已。在平时的工作学习中,咱们要无意识地造就本人的发散性思维,从多角度去对待问题,你可能会发现不一样的风光哦!心愿可能对大家有所启发哦!

在面试中,为了突显本人的独特气质或者人家面试题目就有具体要求的,咱们应用一些看起来高大上的思路,这无可非议。

然而呢,在平时的工作中,我还是更倡议大家:在性能相近的状况下,能应用根底办法解决的个别不要用“低档”办法,因为根底办法出错的概率小很多。就比方明天这道题,其实根底解法的性能是最好的。

少写 BUG,咱们能力有更多的工夫来摸鱼,不是吗?

~

~ 本文完,感激浏览!

~

学习乏味的常识,结识乏味的敌人,塑造乏味的灵魂!

我是〖编程三昧〗的作者 隐逸王,我的公众号是『编程三昧』,欢送关注,心愿大家多多指教!

你来,怀揣冀望,我有墨香相迎!你归,无论得失,唯以余韵相赠!

常识与技能并重,内力和外功兼修,实践和实际两手都要抓、两手都要硬!

正文完
 0