创作纪念日 编程练习 - 斐波那契数列

news2024/12/27 13:09:07

文章目录

  • 我的第一次
  • 今日份练习
    • | 斐波那契数列
  • 憧憬

在这里插入图片描述

我的第一次

第一次浏览CSDN的时候刚开始学C++的时候,当时的课设是《C++ & SQL 2008的学生管理系统》,C++作前段界面、逻辑处理,SQL作为后端服务器支持的题目,当时不太认真学习,上课只顾着玩手机,快结课了才想着赶作业,当时就百度了这个课设题目,恰好点进了一个CSDN博主的文章(具体是哪篇已经不太记得了,只记得是Visual Studio 2010 + (C++) + SQL的开发环境)。在此之前感觉写代码好像也就是把人算数学题的过程变成了代码算数学题的逻辑,当然大一大二两年也是没怎么学编程,导致基础贼烂😭
在这里插入图片描述

从大三开始进实验室慢慢补基础,学东西才意识到编程这玩意只看书,应付考试拿分没意义,还得是多敲键盘。


在这里插入图片描述
第一次在这写文章,是大三进实验室的时候,网上看到Vscode的界面比VS好看多了,就跟着搭环境,这不会那不会,当时折腾了一天,想着那么难搞就记录下来,生怕之后换电脑了又不会整了。也是这一次开始接触Markdown语言😁,确实好用


在这里插入图片描述

今日份练习

恰好,偷懒多天后又练习了一哈哈代码,记录一哈😍

| 斐波那契数列

题目
写一个函数,输入 n,求斐波那契(Fibonacci)数列的第 n 项(即 F ( N ) F(N) F(N) )。斐波那契数列的定义如下:
F 0 = 0 , F 1 = 1 F_0 = 0, F_1 = 1 F0=0,F1=1
F N = F N − 1 + F N − 2 , N > 1 F_N = F_{N - 1} + F_{N - 2}, N > 1 FN=FN1+FN2,N>1

斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

示例 1:

  • 输入:n = 2
  • 输出:1

示例 2:

  • 输入:n = 5
  • 输出:5

思路

  1. 递归法
    很常见的递归解题法,因为从第三项开始,每一项都是前两项的和,所以可以将问题分解成每个项的求值再相加,也就得到了递归的总思想,下面按照递归三部曲确定算法流程

    • 确定递归函数的参数列表:
      每一次递归要计算的每一项的数值,所以参数列表应该代表着当前求值项,那么参数就是下标N
      int Fibonacci1(int N)

    • 确定递归函数的终止条件:
      递归也是一个遍历的过程,而遍历肯定有边界,对于本题来说,边界就是[0, n],那么终止条件就是下标N达到边界时即停止

      if (0 == N)
      {
          return 0;
      }
      if (1 == N)
      {
          return 1;
      }
      
    • 确定递归函数的单层递归逻辑
      单层逻辑要求的是项值,而每一项又等于前两项的和,这就是本题中的单层递归逻辑

      return Fibonacci1(N - 1) + Fibonacci1(N - 2);
      
    • 以求 f 5 f_5 f5为例子,框图如下
      图中可以看出,绿色节点代表着首次计算,蓝色节点代表着已知节点,粉色节点代表着重复计算,每个节点的时间消耗为 O ( 1 ) O(1) O(1),而二叉树的节点数为 O ( 2 n ) O(2^n) O(2n),所以时间复杂度 O ( 2 n ) O(2^n) O(2n)
      在这里插入图片描述

  2. 递归进阶法
    上面提到了常规的递归法会导致多余的资源浪费,当N足够大的时候,计算的时间和资源开销会很大,如果把这些重复计算的资源省略掉,就可以进一步减少算法的时间开销,因为重复计算的项的值都是一样的,那么只要判断当前项是否已经计算过,如果计算过了则直接从之前的结果中取出即可,这样就可以节省重复项的计算时间
    同理下面按照递归三部曲确定算法流程

    • 确定递归函数的参数列表
      与常规递归法不同的是,进阶法需要保存之前计算过的项值,所以需要增加一个数组用来保存这些值
      int Fibonacci2(int N, vector<int> Arr)

    • 确定递归函数的终止条件:
      这一块跟常规递归法没有什么差异,保持一致

    • 确定递归函数的单层递归逻辑
      与常规递归法相比,增加了重复项的对比流程

      if (0 != Arr[N])
      {
          return Arr[N];
      } 
      return Fibonacci2(N - 1, Arr) + Fibonacci2(N - 2, Arr);
      
    • 以求 f 5 f_5 f5为例子,框图如下
      与常规递归法对比,灰色节点代表已经计算过的值,不需要进行计算,那么实际的调用次数就只剩下左边绿色节点和蓝色节点,这样时间复杂度就从 O ( 2 n ) O(2^n) O(2n) 降到 O ( n ) O(n) O(n),但是因为使用了额外的数组进行保存值,所以空间复杂度由原来的 O ( 1 ) O(1) O(1) 升到 O ( n ) O(n) O(n),这就是算法中常见的 空间换时间 策略
      在这里插入图片描述

  3. 动态规划
    既然有递归,那么迭代法也跑不掉。
    从第二项开始,每一项都等于前两项和,那么可以迭代的把遍历过的所有项进行计算,就可以得到最后一项的值了
    f 2 = f 0 + f 1 f_2 = f_0 + f_1 f2=f0+f1
    f 3 = f 1 + f 2 = f 1 + ( f 0 + f 1 ) f_3 = f_1 + f_2 = f_1 + (f_0 + f_1) f3=f1+f2=f1+(f0+f1)
    f 4 = f 2 + f 3 = ( f 0 + f 1 ) + ( f 1 + ( f 0 + f 1 ) ) f_4 = f_2 + f_3 = (f_0 + f_1) + (f_1 + (f_0 + f_1)) f4=f2+f3=(f0+f1)+(f1+(f0+f1))
    . . . . . . ...... ......

那么只需要保存记录好遍历到的每一项的前两项值,并做结果累加就能模拟出上面式子的过程,具体算法流程如下
1. 先记录保存首项和次项值 f 0 , f 1 f_0, f_1 f0,f1
2. 从第二项开始遍历,遍历到的项值等于其前两项的和
3. 遍历到最后一项,结束遍历返回结果值

以上算法唯一需要思考的是第二步,要怎么计算当前遍历项的值?
可以申请一个长度为N的数组,保存之前的每一项值,那么该算法的空间复杂度就跟N有关,为 O ( n ) O(n) O(n),仔细思考其实要保存的只是当前遍历项的前两项,而已经遍历后的项的前两项值其实并不关心,所以只需要申请两个变量保存当前遍历项的前两项值即可,空间复杂度也降为 O ( n ) O(n) O(n)

  • 为什么不申请三个变量,两个保存前两项,一个保存结果值?
    因为当前项计算好之后,遍历到下一项时,会用到当前项的值已经当前项的前一项的值,也就说明总有一个变量时一直跟着遍历往下“共享”的,那么只需要将其中一个变量的功能扩展为先记录前一项的值,后保存为当前项的值就可以实现这个“共享”的目的,最后遍历到 f n f_n fn的时候,这个变量刚好完成了 f n − 1 + f n − 2 f_{n - 1} + f_{n - 2} fn1+fn2的计算,所以这个变量的值就是结果值

代码

int Fibonacci1(int i_uNum)
{
    if (0 > i_uNum)
    {
        return -1;
    }
    else if (0 == i_uNum)
    {
        return 0;
    }
    else if (1 == i_uNum)
    {
        return 1;
    }
    return Fibonacci1(i_uNum - 1) + Fibonacci1(i_uNum - 2);
}

int Fibonacci2(int i_uNum, vector<int>& i_uArr)
{
    if (0 > i_uNum)
    {
        return -1;
    }
    else if (0 == i_uNum)
    {
        return 0;
    }
    else if (1 == i_uNum)
    {
        return 1;
    }
    if (0 != i_uArr[i_uNum])
    {
        return i_uArr[i_uNum];
    }
    return Fibonacci2(i_uNum - 1, i_uArr) + Fibonacci2(i_uNum - 2, i_uArr);
}

int Fibonacci3(int i_uNum)
{
    if (0 > i_uNum)
    {
        return -1;
    }
    else if (0 == i_uNum)
    {
        return 0;
    }
    else if (1 == i_uNum)
    {
        return 1;
    }
    int Fir = 0, Sec = 1;
    for (int i = 2; i <= i_uNum; i++)
    {
        int tmp = Fir;
        Fir = Sec;
        Sec = tmp + Sec;
    }
    return b;
}

小结
进阶递归和动态规划的本质思想是一致的,区别在于:

  • 进阶递归 — 从顶至低: 求 f n f_n fn 需要 f n − 1 f_{n - 1} fn1 f n − 2 f_{n - 2} fn2, ⋯ \cdots ;求 f 2 f_2 f2 需要 f 1 f_1 f1 f 0 f_0 f0 ;而 f 1 f_1 f1 f 0 f_0 f0 已知;
  • 动态规划 — 从底至顶: 将已知 f 0 f_0 f0 f 1 f_1 f1 组合得到 f 2 f_2 f2, ⋯ \cdots ;将 f n − 2 f_{n - 2} fn2 f n − 1 f_{n - 1} fn1 组合得到 f n f_n fn

憧憬

希望以后能好好学习,接触更多的新东西,赚大钱😶
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/54578.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

化纤企业净利润下滑,纺织企业如何利用APS排产减轻盈余压力

根据国家统计局数据&#xff0c;2022年前三季度&#xff0c;全国规模以上纺织企业工业增加值同比减少0.4%&#xff0c;营业收入同比增长3.1%&#xff0c;利润总额同比减少23.6%&#xff0c;增速均较上年同期有所放缓。 从全产业链看&#xff0c;中下游印染、长丝织造、服装等分…

Qt之读写文件

1.思路 读写文件的基本操作&#xff1a; 读文件 写文件 打开文件 打开文件 读取文件 写入文件 关闭文件 关闭文件 2.QFile实现读写文件 QFile类提供读写文件的接口。 它的构造函数如下&#xff1a; QFile(const QString & name) QFile(QObject * parent) QFile(c…

点击化学 PEG 试剂:1802907-92-1,Mtz-PEG4-NHS,甲基四嗪-四聚乙醇-活性酯

【中文名称】甲基四嗪-四聚乙醇-活性酯 【英文名称】 Methyltetrazine-PEG4-NHS ester&#xff0c;Mtz-PEG4-NHS 【结 构 式】 【CAS号】1802907-92-1 【分子式】C24H31N5O9 【分子量】533.54 【基团部分】Methyltetrazine 【纯度标准】95% 【包装规格】5g&#xff0c;10g&…

安卓有哪些耳机好用?好用的安卓蓝牙耳机推荐

市面上的蓝牙耳机五花八门&#xff0c;许多消费者在选购的时候不知道如何选择&#xff0c;除了苹果以外&#xff0c;其他的都要细心参考一下&#xff0c;由于苹果耳机市场的价格昂贵&#xff0c;不少的人选择其他品牌的替代&#xff0c;作为一位追求性价比的消费者而言&#xf…

HTML5期末大作业:HTML+CSS茶叶官网网页设计实例 企业网站制作

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

Dubbo底层网络连接模型

在Dubbo中&#xff0c;有两个参数⽤来配置服务消费者和服务提供者直接的socket连接个数&#xff1a; shareconnections&#xff1a;表示可共享的socket连接个数connections&#xff1a;表示不共享的socket连接个数 服务A的shareconnections为2时&#xff0c;服务A的消费者会向…

CANoe-vTESTstudio之Waveform编辑器

1. 什么是Waveform编辑器 Waveform Editor,波形编辑器,可以创建曲线(随时间变化值变化的模式)来刺激信号和系统变量。在刺激过程中可以使用checkpoints(检查点)来测试被测系统的行为 简单来说,就是在一个坐标轴上,x轴是时间,y轴是刺激的信号或系统变量值。在指定的时…

算法设计与分析期末复习不挂科

算法的基本概念 算法概念 通俗讲:算法是解决问题的一种方法或一个过程 严格讲:算法是解某一特定问题的一组有穷规则的集合 且满足以下性质: 有限性:算法在执行有限步之后必须终止确定性:算法的每一个步骤都有精确的定义,要执行的每一个动作都是清晰的,无歧义的输入:一个算法有…

关于nodejs调用c/c++代码的一些感悟

帮客户解决问题&#xff0c;他们做的业务涉及到硬件&#xff0c;但是桌面端程序员离职&#xff0c;临时接手的人员&#xff0c;只会node&#xff0c;于是希望通过node调用c 基本套路&#xff0c;使用ffi和ref插件&#xff0c;打开设备正常&#xff0c;但就是无法读取数据。 接…

【Python游戏】用Python实现一个测试你智商的小游戏——24点,过不了三关的都是细狗 | 附带源码

前言 好咯&#xff0c;包子们下午好 今天小编主要是过来测试一下大家的智商&#xff0c;没别的意思&#xff0c;不是看不起大家&#xff0c;我感觉今天实现的小游戏&#xff0c;可能大家真的过不了三关&#xff01; 哈哈哈&#xff0c;废话不多说吧 直接开始我们的游戏实现功能…

五、【React-Router6】路由表 useRoutes() + Outlet

文章目录1、useRoutes() 介绍2、简单 CODING2.1、项目结构2.2、routes.js2.3、App.js2.4、Result3、嵌套 Outlet CODING3.1、项目结构3.2、routes.js3.3、Home.js3.4、App.js3.5、Result1、useRoutes() 介绍 原来写的路由管理如下 <Routes><Route path/about elemen…

codeforces:C. Almost All Multiples【构造 + 贪心】

目录题目截图题目分析ac code总结题目截图 题目分析 现在p1 x, pn 1如果我们一开始按1234…这样放字典序是最小的所以根据这个思路&#xff0c;我们还是按这个构造&#xff1a;那么我们的n被挤出来了&#xff0c;只能放到px上所以如果一开始x不能整除n的话&#xff0c;就直接…

Linux安装MySQL【Ubuntu20.04】

操作系统&#xff1a;Ubuntu20.04 使用工具&#xff1a;xshell7、xftp7 MySQL版本&#xff1a;5.7 一、删除Linux系统下自带的mariadb &#xff08;因为centos自带一个老版Mariadb 与MySQL冲突&#xff09; 如果没有找到Mariadb直接跳过 #查找Mariadb rpm -qa | grep maria…

面试总结2

用时&#xff1a;40min 自我介绍hashset存储对象怎么进行判断是否重复 Synchronized底层实现原理 Synchronized锁的升级过程 讲讲开发中常用到的spring注解spring事务&#xff0c;传播机制&#xff0c;隔离级别说一说你常用的git命令说一说你对IOC、AOP的理解1、hashset存储对…

[Linux打怪升级之路]-秒懂进程地址空间

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正。 目录 一、C/C下…

【GIT】常用操作总结

一、在本地仓库及远程仓库创建分支&#xff0c;并建立关联关系。 1、创建本地分支&#xff0c;如图&#xff1a; 2、填写分支名称&#xff0c;勾选Checkout branch&#xff1a; 3、提交本地分支到远程分支&#xff1a; 右键选择Git -- Repository -- push&#xff1a; push的时…

Python爬取的网页,需要解码怎么办

前言 本文是该专栏的第26篇,后面会持续分享python的爬虫干货知识,记得关注。 很多时候,在用爬虫采集数据的时候,采集到的源码内容并非我们想要的正确信息,使用正则或者Xpath匹配到的信息也需要我们再次解码才能拿到精准的数据。最近也正是球迷朋友们非常关注卡塔尔世界杯…

[操作系统笔记]基本分段存储管理

内容系听课复习所做笔记&#xff0c;图例多来自课程截图 分段原理 与“分页”最大的区别就是&#xff1a;离散分配时所分配地址空间的基本单位不同 分页是不管程序的逻辑的&#xff0c;规定了页大小就是这么多&#xff0c;但是分段是依据程序自身逻辑来划分的&#xff08;分页的…

micro-app-源码解析4-数据通信篇-终篇

沙箱篇官方讲解地址 https://github.com/micro-zoe/micro-app/issues/21 1. 带着问题进行阅读 在做框架的时候&#xff0c;没法避免的遇见父子通信和兄弟通信的问题&#xff0c;但是如何实现通信这是个每个框架需要解决的问题。1.1 如何选择父子通信的方式 最好的方式应该是…

IOC操作Bean管理(基于注解方式)

IOC 控制反转&#xff0c;把创建对象过程交给Spring进行管理。 目录 什么是注解 Bean 管理注解方式&#xff08;创建对象&#xff09; 基于注解方式实现对象创建 第一步&#xff1a;引入依赖 第二步&#xff1a;开启组件扫描 创建类&#xff0c;在类上面添加创建对象注解…