算法题目-斐波那契数列问题

(文章参考来源)

    https://zhidao.baidu.com/question/2115713113203375747.html

    https://www.jianshu.com/p/78243311b8ed

题目

    有一对兔子,从出生后第3个月起每个月都生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 

    分析,每个月份的兔子数(单位:对)是:

    1

    1

    2(T1生了T2)

    3(T1生了T3)

    5(T1生了T4,T2生了T5)

    8(T1生了T6,T2生了T7,T生了T8)

    13(T4、T5也加入了生兔子大军)

    从数据可见,每个月的兔子数(单位:对)形成了菲波那切数列。

javaScript code

1) 正常递归版本

function fibonacciFunc(n){

  if(n == 0)

    return 0

  else if(n == 1)

    return 1

  else

    return fibonacciFunc(n-1)+fibonacciFunc(n-2)

}

代码优美逻辑清晰。但是这个版本有一个问题即存在大量的重复计算。如:当n为5的时候要计算fibonacci(4) + fibonacci(3)当n为4的要计算fibonacci(3) + fibonacci(2),这时fibonacci(3)就是重复计算了。运行fibonacci(50)等半天才会出结果。

2)for循环版本

function fibonacci(n){

  let last = 1

  let last2 = 0

  let current = last2

  for(let i=1; i<= n; i++){

    last2 = last

    last = current

    current = last+last2

  }

  return current

}

这个版本没有重复计算问题,速度也明显快了很多。这并不代表循环比递归好。循环的问题在于状态变量太多,为了实现fibonacci这里使用了4个状态变量(last,last2,current,i)而状态变量 在写、修改、删除的过程中需要格外小心,它会让我有不安全感。状态变量多了阅读起来也不那么优美了。

3)去除重复计算的递归版本

function fib(n){

  function fib_(n, a, b){

    if(n == 0)

      return a

    else

      return fib_(n-1, b, a+b)

  }

  return fib_(n, 0, 1)

}

把前两位数字做成参数巧妙的避免了重复计算,性能也有明显的提升。n做递减运算,前两位数字做递增(斐波那契数列的递增),这段代码一个减,一个增,初看时有点费脑力。按照我的习惯一般是全增,让n从0开始到n。

你可能感兴趣的:(算法题目-斐波那契数列问题)