循环实现斐波那契数列(最优解)

斐波那契数列:
f(n)=f(n-1)+f(n-2)(n>2) f(0)=1;f(1)=1;
即有名的兔子繁衍问题
在本篇文章我将会给出三种解法

一、最优解: 

#include<stdio.h>
#include<stdlib.h>
long long Fib(long long N)
{
    long long first = 1;
    long long second = 1;
    long long ret = 0;
    for (int i = 3; i <=N; ++i)
    {
        ret = first + second;
        first = second;
        second = ret;
    }
    return second;
}
int main()
{
    long long num = 0;
    num=Fib(10);
    printf("循环:%d\n", num);
    system("pause");
    return 0;
}

时间复杂度:O(N)
空间复杂度:O(1)(创建了四个对象,是常数,所以可忽略不计)
此种方法是"最优方法"
优点:时间复杂度和空间复杂度最低,而且可读性高

 

二、递归实现斐波那契数列

#include<stdio.h>
#include<stdlib.h>
long long Fib(long long N)
{
    if (N < 3)
        return 1;
    else
        return Fib(N - 1) + Fib(N - 2);
}
int main()
{
    long long num = 0;
    num=Fib(10);
    printf("递归:%d\n", num);
    system("pause");
    return 0;
}

此种方法的缺陷:重复计算的次数太多,效率低
   例如:在下图中,F(3)就重复计算了 "3次"
时间复杂度:O(2^N)
空间复杂度:O(N)

这里写图片描述 

三、 递归(尾递归)实现斐波那契数列,但是时间复杂度尽可能低

"尾递归的前提是递归"
(1)定义:在一个程序中,执行的最后一条语句是对自己的调用,而且没有别的运算

(2)尾递归的实现:是在编译器优化的条件下实现的

  编译器优化:
     递归的第一次调用时会开辟一份空间,此后的递归调用不会再开辟空间,而是在刚才开辟的空间上做一些修改,实现此次递归,例如在本题中求Fib(10),编译器会给Fib(10)的调用开辟栈帧,调用Fib(9)的时候不会再重新开辟栈帧,而是在刚开辟的栈帧上做一些修改,因为递归的每一次调用都是一样的流程,只是会有一些数据不同,所以不会再开辟空间。

注:vs一般都支持优化,Debug下编译器不会优化哦,一定要在Release模式下。

 

#include<stdio.h>
#include<stdlib.h>
long long Fib(long long first,long long second ,long long N)
{
    if (N < 3)
        return 1;
    if (N == 3)
        return first + second;
    return Fib(second, first + second, N - 1);
}
int main()
{
    long long num = 0;
    num=Fib(1,1,10);
    printf("尾递归:%d\n", num);
    system("pause");
    return 0;
}


 

此种方法是尾递归,很大程度的减小了第一种方法(递归实现斐波那契数列)的时间复杂度
时间复杂度:O(N-2)约等于0(N)
空间复杂度:O(N-2)约等于0(N)(编译器如果优化的话是O(1))

此种递归是尾递归

 

 

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值