面试题9:斐波那契数列

部署运行你感兴趣的模型镜像

题目一:写一个函数,输入n,求斐波那契数列的第n项。斐波那契数列的定义如下:

无标题


分析

根据上述公式,我们可以很容易地写出如下递归代码:

long long Fib(int x)
{
    if(x==0 || x==1)
        return x;
    return Fib(x-1,count)+Fib(x-2,count);
}

不过递归方式的时间复杂度是O(2^n),空间复杂度都是是O(n),增长的很厉害,用来解释递归原理还可以,是无法应用的实际中去的。

那我们就可以把递归该成循环,使时间复杂度降到O(n)。

代码如下

long long Fib(int x)
{
    if(x<=1)
        return x;
    int a=0,b=1,res;
    int i;
    for(i=0;i<x-1;++i)
    {
        res=a+b;
        a=b;
        b=res;
    }
    return res;
}

一般到这里就可以了,但我们现在有一个时间复杂度为O(logN)的方法,讲解如下:

有一个数学公式:无标题
这个公式在此不做证明,有兴趣的读者可以自己用数学归纳法试着证明一下。

现在我们就将斐波那契问题转化矩阵乘法的问题了。但如果还是以普通乘法来计算的话,时间复杂度跟循环无异。所以需要对其优化。

  1. 1. 对于矩阵乘方,常规算法需要O(n3)时间,《算法导论》上介绍了一种Strassen算法,可以将计算的时间复杂度压缩到O(nlg7)。(lg7的值在2.80到2.81之间)在此不做验证。
  2. 2. 假设n为偶数,an=an/2*an/2,所以我们可以利用乘方的这种性质来计算,时间复杂度缩减到O(lonN)。

    代码如下:

    vector<vector<unsigned long long int> > MultiMatrix(vector<vector<unsigned long long int> > matrix1,vector<vector<unsigned long long int> > matrix2)
    {
        if(matrix1.size()<=0 || matrix2.size()<=0)
            return vector<vector<unsigned long long int> >();
        vector<vector<unsigned long long int> > res;
        int i,j,k;
        res.resize(matrix1.size());
        for(i=0;i<matrix1.size();++i)
        {
            res[i].resize(matrix2[0].size());
            for(j=0;j<matrix2[0].size();++j)
            {
    
                res[i][j]=0;
                for(k=0;k<matrix2.size();++k)
                {
                    res[i][j]+=matrix1[i][k]*matrix2[k][j];
                }
            }
        }
        return res;
    }
    
    vector<vector<unsigned long long int> > calc(vector<vector<unsigned long long int> > matrix,int x)
    {
        int i;
        vector<vector<unsigned long long int> > res=matrix;
        for(i=0;i<x-1;++i)
        {
            res=MultiMatrix(matrix,res);
        }
        return res;
    }
    
    unsigned long long int Fib(int x)
    {
        if(x==0 || x==1)
            return x;
        vector<vector<unsigned long long int> >matrix;
        matrix.resize(2);
        matrix[0].resize(2);
        matrix[1].resize(2);
        matrix[0][0]=matrix[0][1]=matrix[1][0]=1;
        matrix[1][1]=0;
        return calc(matrix,x-1)[0][0];
    }
    

以上

如果你有任何想法或是可以改进的地方,欢迎和我交流!

完整代码及测试用例在github上:点我前往

您可能感兴趣的与本文相关的镜像

Kotaemon

Kotaemon

AI应用

Kotaemon 是由Cinnamon 开发的开源项目,是一个RAG UI页面,主要面向DocQA的终端用户和构建自己RAG pipeline

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值