JavaScript解斐波那契(Fibonacci)数列的有用解法

JavaScript解斐波那契(Fibonacci)数列的有用解法

我们常常会在口试题中看到以下题目:输入n,求斐波那契数列的第n项,斐波那契数列的定义以下:

F(0)=0, F(1)=1, n>1时,F(n)=F(n-1)+F(n-2)。

一种效力很低的解法

当碰到这类函数时,我们很轻易的想到递归函数,解法以下:

function fibonacci(n) {
  if(n <= 1) {return n};
  else {
    return fibonacci(n-1) + fibonacci(n-2);
  }
}

这个要领确切能处置惩罚这道题目,但递归的解法并不合适这道题目,用递归解法将会有很严重的效力题目,我们以f(10)为例剖析一下缘由:

《JavaScript解斐波那契(Fibonacci)数列的有用解法》

由上述图片我们能够看出,要想求得f(10),须要先求得f(8)和f(9),一样,要想求得f(9),也要求得f(7)和f(8)。不难看出,树结构当中许多结点是反复的,而且反复的节点数会跟着n的增大而急剧增大,这意味着盘算量将会跟着n的增大而急剧增大。事实上,递归所需的时刻复杂度是以n的指数体式格局递增的,由此我们能够尝尝当n为100时须要消耗的时刻会有多长,这是难以接收的。

动态计划解法

形成效力低下的主要缘由就是反复盘算太多,我们只需想个办法防止反复盘算即可,这里有个很轻易的算法:

var fib = 0,
    fib1 = 0,
    fib2 = 1;
function fibonacci(n) {
  if(n <= 1){
    return n;
  } else {
    for(var i =1; i < n; ++i) {
      fib = fib1 + fib2;
      fib1 = fib2;
      fib2 = fib;
    }
    return fib;
  }
}

邃晓这类要领很简单,我们只是从下往上盘算,起首依据f(0)和f(1)算出f(2),再依据f(1)和f(2)算出f(3),顺次类推我们就能够算出第n项了,而这类算法的时刻复杂度仅为O(n),比递归函数的写法效力要大大加强。

Memoization

我们还能够将已获得的数列中心项保存起来,若下次盘算的时刻我们先查找一下,若前面已涌现过则不必再反复盘算了。

在JavaScript中,递归是拖慢剧本运转速率的罪魁祸首之一,太多的递归会让浏览器越来越慢以致奔溃,这是须要我们处置惩罚的机能题目。

我们能够应用memoization手艺来替换函数中太多的递归挪用,memoization是一种能够缓存之前运算效果的一种手艺,当在实行运算操纵时,我们先从缓存对象中读取看看是不是有我们须要读取的值,如有则直接从缓存对象中读取,若没有则举行盘算,并将缓存效果存入缓存对象中。

下面是一个能够处置惩罚许多范例递归函数的memoizer()函数:

`function memoizer(fun, cache) {

 cache = cache || {};
 var shell = function(arg) {
   if( ! (arg in cache)) {
     cache[arg] = fun(shell, arg);
   }
   return cache[arg];
 } ;
 return shell;

}`

个中第一个参数为原有函数,第二个参数为缓存对象,是可选参数(由于并非一切递归函数都包括初始信息)。起首将缓存对象的范例从数组转换为对象,如许就能够适用于那些不是返回整数的递归函数。应用in操纵符推断参数是不是已包括在了缓存里,会比测试cache[arg]更平安些,由于undefined是一个有用的返回值(这里实在我也不太邃晓,弄清楚后会补上)。

接下来我们就能够挪用memoizer来解这个这个题目:

var fibonacci = memoizer(function(fibon, n) {
  return fibon(n - 1) + fibon(n - 2);
}, {'0' : 0, '1' : 1});

这时候我们就能够经由过程fibonacci(100)来实行函数,一样应用此种要领复杂度为O(n),大大优化了实行效力。

跋文

个人更喜好memoizer的解法,由于我以为这类解法越发的文雅,应用了JavaScript函数式编程的特征,异常值得自创。

在我看来,函数的实行效力很主要,勿以事小而不为,日常平凡多积聚一些优异的解法,从日常平凡的小知识点动身,逐步提高,假以时日终将也能够写出文雅高效力的要领

    原文作者:胡洋
    原文地址: https://segmentfault.com/a/1190000008591467
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞