JavaScript输出斐波那契数列的实现方法

 更新时间:2021年06月27日 10:28:02   作者:隐逸王  
斐波那契数列来源于兔子繁殖问题,所以也叫兔子序列,下面这篇文章主要给大家介绍了关于JavaScript输出斐波那契数列的实现方法,需要的朋友可以参考下

题目

有这么一道题目需要我们来解答:

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

分析

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

对于这道题,可以不用理会这个陌生概念,我们只需要关心后面它给出的数字规律即可。

我们可以看到,规律总结起来就一句话:从第三位开始,后面每项的值等于前两项之和,用式子表示的话就是:an = an-1 + an-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 。
  • 计算第三项的值为 1 + 1 = 2 。
  • 计算第四项的值为 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,我们才能有更多的时间来摸鱼,不是吗?

到此这篇关于JavaScript输出斐波那契数列的文章就介绍到这了,更多相关JS输出斐波那契数列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 如何使用proxy实现一个简单完整的MVVM库的示例代码

    如何使用proxy实现一个简单完整的MVVM库的示例代码

    这篇文章主要介绍了如何使用proxy实现一个简单完整的MVVM库的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • 使用json-server简单完成CRUD模拟后台数据的方法

    使用json-server简单完成CRUD模拟后台数据的方法

    这篇文章主要介绍了使用json-server简单完成CRUD模拟后台数据的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • Uniapp微信小程序实现全局事件监听并进行数据埋点的方法

    Uniapp微信小程序实现全局事件监听并进行数据埋点的方法

    niapp起源 uni-app是一个使用Vue.js开发所有前端应用的框架,下面这篇文章主要给大家介绍了关于Uniapp微信小程序实现全局事件监听并进行数据埋点的相关资料,需要的朋友可以参考下
    2022-11-11
  • 使用JavaScript实现轮播图效果

    使用JavaScript实现轮播图效果

    这篇文章主要为大家详细介绍了使用JavaScript实现轮播图效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • JavaScript性能优化总结之加载与执行

    JavaScript性能优化总结之加载与执行

    本文详细介绍了如何正确的加载和执行JavaScript代码,从而提高其在浏览器中的性能。对JavaScript学习者很有帮助,有需要的可以参考学习。
    2016-08-08
  • javascript实现图片延迟加载方法汇总(三种方法)

    javascript实现图片延迟加载方法汇总(三种方法)

    看到一些大型网站,页面如果有很多图片的时候,当你滚动到相应的行时,当前行的图片才即时加载的,这样子的话页面在打开只加可视区域的图片,而其它隐藏的图片则不加载,一定程序上加快了页面加载的速度,跟着小编一起学习javascript实现图片延迟加载吧
    2015-08-08
  • 详解Typescript 内置的模块导入兼容方式

    详解Typescript 内置的模块导入兼容方式

    这篇文章主要介绍了详解Typescript 内置的模块导入兼容方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • javascript自定义startWith()和endWith()的两种方法

    javascript自定义startWith()和endWith()的两种方法

    js中自定义startWith()和endWith()方法有两种,在本文将为大家详细介绍下,感兴趣的朋友不要错过
    2013-11-11
  • JS高阶函数原理与用法实例分析

    JS高阶函数原理与用法实例分析

    这篇文章主要介绍了JS高阶函数原理与用法,结合实例形式分析了javascript函数式编程、一等函数、高阶函数等相关概念、原理及使用技巧,需要的朋友可以参考下
    2019-01-01
  • 理解 JavaScript 预解析

    理解 JavaScript 预解析

    JavaScript是解释型语言是毋庸置疑的,但它是不是仅在运行时自上往下一句一句地解析的呢?
    2009-10-10

最新评论