面试官期待的实用斐波那契解法

单说斐波那契数列

我们熟悉的斐波那契数列的问题即:

  • 写一个函数,输入 n , 求斐波那契数列的第 n 项 。
  • 斐波那契数列的定义如下
              0                  n=0
f(n) =       1                 n=1
              f(n-1)+f(n-2)      n>1


挑剔的面试官不会喜欢的解法,效率很低

代码:

long long Fibonacci1(const unsigned n){
    if(n<= 0 ) return 0;
    if(n==1) return 1;
    return Fibonacci1(n-1)+Fibonacci1(n-2);
}

我们乍一看我们刚学习斐波那契数列的时候就是这种解题思路,我们几乎非常快就能写出这个函数
但是面试官会告诉你:

来啊,我们来看一下 输入 n = 10 的递归过程

                    f(10)
                    /    \
                f(9)     f(8)
               /   \      /  \
             f(8)  f(7) f(7)  f(6)
             .....................继续分解下去

我们不难发现,重复递归计算的次数越来越多,因此效率很低,面试官不喜欢,我们来介绍下一种优化递归的解法。





面试官期待的解法1:记忆化数组优化重复计算

思路:利用数组记录斐波那契数列中已经计算出的数列项值,之后重复调用时,直接返回记忆的数列项值,这样就会避免重复递归计算。

所需条件:记忆化数组 memo

代码:

const  unsigned  n= 100;     //输入的n
int memo[n+2];               //定义记忆化数组
void InitMemoArr(int arr[]){
    memset(arr,-1,n);  //将数组元素的初始值设置为-1
    arr[0] = 0;
    arr[1] = 1;
}
long long Fibonacci2(const  unsigned  n) {
    InitMemoArr(memo);
    if(memo[n]!=-1) return memo[n];
    return memo[n]=Fibonacci2(n-1)+Fibonacci2(n-2);
}




面试官期待的解法2:直接利用循环过程累加计算

思路: 我们利用 f(1)和f(2)能计算出 f(3) …以此循环类推能得出第 n 项。
所需条件

      例如:求 4 项的值
      f (2) = f(1) + f(0)
      f (3) = f(2) + f(1)
      f (4) = f(3) + f(2)

我们利用 3个变量:fibNminusOne,fibNminusTwo,fibN, 关系如下:

        fibN = fibNminusOne+fibNminusTwo;

当得出新的 fibN 后,fibNminusOne,fibNminusTwo,fibN转换关系如下:

        fibN = fibNminusOne+fibNminusTwo;
        //新 fibN 得出后,为fibNminusOne,fibNminusTwo重新赋值,即递增项数值
        fibNminusTwo = fibNminusOne;
        fibNminusOne = fibN;

这样循环后就能得出 第 n 项的值(fibN)了

代码:

long long Fibonacci3(const unsigned n){
    int result[2] = {0,1};
    if(n<2)
        return result[n];

    long long fibNminusOne = 1;   //递推的第一项
    long long fibNminusTwo = 0;
    long long fibN = 0;
    for (int i = 2; i <=n ; ++i) {
        
        fibN = fibNminusOne+fibNminusTwo;
        fibNminusTwo = fibNminusOne;
        fibNminusOne = fibN;

    }
    return fibN;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值