【C语言】斐波那契数列四种优化求解

题目:
  • 使用递归和非递归的方法分别实现求第n个斐波那契数,那么什么是斐波那契数。斐波那契数列指的是这样一个数列:0 、1、1、2、3、5、8、13、21,后面的每一个数是前面两个数的和。(由于数列增长快,int型就只能算到近50位,所以尽可能采用long long型)*

这里写图片描述
这里写图片描述

方法一:递归实现

//时间复杂度O(N^2)
//空间复杂度o(N)
long long fib(size_t n)
{
	return (n < 2) ? n : (fib(n - 1) + fib(n - 2));
}

在这里插入图片描述
缺点:
①只是使用于n比较小的时候,否则效率低,因为会做很多次重复操作
②而且该例递归属于多分支递归,容易造成栈溢出

方法二:非递归实现(迭代)

//时间复杂度O(N)
//空间复杂度O(1)
long long fib(size_t n)
{
	long long n1 = 0,n2= 1,n3=n;
	int i = 0;
	for(i = 2;i<=n;i++)
	{
		n3 = n1+n2;
		n1 = n2;
		n2 = n3;
	}
	return n3;
}

方法三:尾递归实现

//时间复杂度O(N)
long long fib(long long first,long long second,size_t n)
{
	if(n<2)
	{
		return n;
	}
	if(2 == n)
	{
		return first+second;
	}
	return fib(second,first+second,n-1);
	
}

在这里插入图片描述

优点:
①计算结果参与到下一次的计算,从而减少很多重复计算量
②原本朴素的递归产生的栈的层次像二叉树一样,以指数级增长,但是现在栈的层次却像是数组,变成线性增长了,简单来说,原本栈是先扩展开,然后边收拢边计算结果,现在却变成在调用自身的同时通过参数来计算。

尾递归可以转换成迭代算法

总结
尾递归的本质是:将单次计算的结果缓存起来,传递给下次调用,相当于自动累积

方法四:矩阵乘法实现 (最优解)

  • 常识:
    这里写图片描述
    这里写图片描述
  • 快速幂
#include <stdio.h>
//base 底数 ,exp 指数 
int qpow(int base,int exp)
{
if (0==exp ) return 1;

int ret=1;

while(exp)
{
    if(exp&1)//exp最右边一位 按位与&
    {
        ret=ret*base;
    }
    base=base*base;
    exp>>=1;//右移一位 
}
return ret;
} 

int main()
{
    printf("%d",qpow(3,5));
    return 0;
}

:此方法借鉴与 谷歌面试题精选

#include<iostream>
#include<string>
using namespace std;
 
 //定义2×2矩阵;
struct Matrix2by2
{
     //构造函数
     Matrix2by2
          (
         long m_00,
         long m_01,
         long m_10,
         long m_11
     )
     :m00(m_00),m01(m_01),m10(m_10),m11(m_11)
     {
     }
 
     //数据成员
     long m00;
     long m01;
     long m10;
     long m11;
 };
 
 //定义2×2矩阵的乘法运算
 Matrix2by2 MatrixMultiply(const Matrix2by2& matrix1,const Matrix2by2& matrix2)
 {
     Matrix2by2 matrix12(1,1,1,0);
     matrix12.m00 = matrix1.m00 * matrix2.m00 + matrix1.m01 * matrix2.m10;
     matrix12.m01 = matrix1.m00 * matrix2.m01 + matrix1.m01 * matrix2.m11;
     matrix12.m10 = matrix1.m10 * matrix2.m00 + matrix1.m11 * matrix2.m10;
     matrix12.m11 = matrix1.m10 * matrix2.m01 + matrix1.m11 * matrix2.m11;
     return matrix12;
 
 }
 
 
 //定义2×2矩阵的幂运算
  Matrix2by2 MatrixPower(unsigned int n)
 {
     Matrix2by2 matrix(1,1,1,0);
     if(n == 1)
     {
         matrix = Matrix2by2(1,1,1,0);
     }
     else if(n % 2 == 0)
     {
         matrix = MatrixPower(n / 2);
         matrix = MatrixMultiply(matrix, matrix);
     }
     else if(n % 2 == 1)
     {
         matrix = MatrixPower((n-1) / 2);
         matrix = MatrixMultiply(matrix, matrix);
         matrix = MatrixMultiply(matrix, Matrix2by2(1,1,1,0));
     }
     return matrix;
 }
 //计算Fibnacci的第n项
 long Fibonacci(unsigned int n)
 {
     if(n == 0)
         return 0;
     if(n == 1)
         return 1;
 
     Matrix2by2 fibMatrix = MatrixPower(n-1);
     return fibMatrix.m00;
     
 }
 
 int main()
 {
     cout<<"Enter A Number:"<<endl;
     unsigned int number;
     cin>>number;
     cout<<Fibonacci(number)<<endl;
     return 0;
 }

结语:

努力的人生是完美的,因为不曾后悔过!!!

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农印象

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值