Fibonacci(斐波纳契)数列求解 zz

斐波那契数列(Fibonacci sequence)【思路及实现】 定义 斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N... 阅读详情

  描述了动物繁殖数量、植物花序变化等自然规律。作为一个经典的数学问题,Fibonacci数列常作为例子出现在程序设计、数据结构与算法等多个相关学科中。

  下面简单地分析一下常见的Fibonacci数列求解算法。

  1、递归法。大多数教材在讲解递归算法时总喜欢以Fibonacci数列为例,这是因为我们可以直观地从定义公式的第三行看出Fibonacci数列的递归性。其C++实现如下:

unsigned long Fib(int n)
            {
            if (n <= 1) {
            return n;
            } else {
            return Fib(n - 1) + Fib(n - 2);
            }
            }


  递归算法与定义公式十分吻合,容易理解,但计算过程存在大量重复的运算,时间复杂度达到了O(2^n),使用的内存空间也随着函数调用栈的增长而增长。这显然不适于实用的程序。

  2、表驱动的递归法。这里不提纯粹的表驱动法,因为对于项数未知的Fibonacci数列开启大片的空间来换取时间未免不值得且不负责。我们只是为了消除递归法中大量重复的运算,可以将已经计算过的中间值存入一个表,已备后续使用:

#define MAX_LOG 20
            static unsigned long Logs[MAX_LOG] = {0};
            unsigned long Fib(int n)
            {
            if (n <= 1) {
            return n;
            } else if (n < MAX_LOG && Logs[n] != 0) {
            return Logs[n];
            } else {
            Logs[n] = Fib(n - 1) + Fib(n - 2);
            return Logs[n];
            }
            }



  当n小于保存的表长时,由于每个中间值只计算一次,时间复杂度降为O(n)。但随着n的增大,要想维持O(n)的时间复杂度,就必须扩大保存的表长,这就造成了存储空间的浪费。

  3、迭代法。求Fibonacci数列第n项时虽然要用到前面两项的值,但它们仅作为临时计算的中间值,不作为结果输出,因此无保留的必要,完全可以转化成迭代法求解:

unsigned long Fib(int n)
            {
            int i;
            unsigned long a = 0, b = 1, c;
            if (n <= 1) {
            return n;
            } else {
            for (i = 2; i <= n; i++) {
            c = a + b;
            a = b;
            b = c;
            }
            return c;
            }
            }



  迭代法的时间复杂度为O(n),使用的内存空间也不会动态上涨。个人认为Fibonacci数列更适宜作为迭代法而非递归法的典例出现在教材上。

  下面给出两种数学性较强的算法。考虑到表达的简洁性,用Matlab实现:

  4、转移矩阵法。此方法通常见于线性代数中的Markov过程示例。Fibonacci数列第n项与第n-1项可以通过转移矩阵的n-1次迭代求出:



  代码如下:

function y = Fib(n)
            first = [1; 0];
            trans = [1 1; 1 0];
            last = trans ^ (n - 1) * first;
            y = last(1, 1);
            end



  此算法的时间复杂度相当于计算矩阵乘方的时间复杂度。在计算2阶矩阵n次方时,如果直接按矩阵乘法定义式展开,不加特别优化,其时间复杂度为O(n)。

  5、通项公式法。Fibonacci数列的通项公式如下(证明略):



  利用通项公式可以得到Fibonacci数列的任何项:

function y = Fib(n)
            sr5 = sqrt(5);
            y = uint32((((1 + sr5) / 2) ^ n - ((1 - sr5) / 2) ^ n) / sr5);
            end



  该方法的时间复杂度貌似为O(1),但我们还应该考虑乘方运算的时间消耗。不加特别优化时,用乘法实现n次乘方的时间复杂度为O(n)。考虑到浮点数计算效率和精度问题,此方法在计算机实现时不如转移矩阵法。

  下面再给出两种对计算机实现有特别意义,但同时有一定局限性的实现方法(只是实现方法,不能称为新的算法)。其中使用了一些C++编程技巧,对使用其它语言实现也有一定的参考价值:

  6、模板元编程法。通常我们在C++中使用模板,仅限于类模板与函数模板。事实上C++支持模板元编程,理论上可以在编译时执行任何计算(甚至包含选择、循环、递归等结构)。代码如下:

#define Fib(N) FibT<N>::Val
            template<int n> struct FibT
            {
            enum
            {
            Val = FibT<n - 1>::Val + FibT<n - 2>::Val
            };
            };
            template<> struct FibT<0>
            {
            enum
            {
            Val = 0
            };
            };
            template<> struct FibT<1>
            {
            enum
            {
            Val = 1
            };
            };



  我们用一个结构体作为模板的载体,用一个枚举值保存运算结果。其中第一个模板为基本递归过程(使用递归算法是为了说明的简便,完全可以用其它算法替代,以加速编译过程),后两个模板为n=0、1时的模板特化。通过#define语句将模板调用简写成类似函数调用的方式。程序在编译时运算所需的Fibonacci数列项,将结果作为常量嵌入编译好的程序。运行时直接使用结果,时间复杂度真正地变成了O(1)。但这一方法最大的局限就是只能对常量嵌入,程序中出现诸如计算Fib(i++)的情况则无能为力。尽管如此,这比在代码中手工计算并写入所需的值要直观准确,比通过纯粹的表驱动法“空间换时间”要方便快捷。

  7、函数对象法。此方法主要用于C++ STL编程的通用算法方面,其执行行为也有别于以上其它方法:

class Fib
            {
            public:
            Fib() : a(0), b(1), n(0)
            {
            }
            unsigned long operator()()
            {
            if (n <= 1) {
            n++;
            return n - 1;
            } else {
            int c;
            c = a + b;
            a = b;
            b = c;
            return c;
            }
            }
            private:
            int a, b, n;
            };


  这个函数类对象的行为可以理解为一个“Fibonacci数列发生器”,其测试性调用如下,程序将依次打印

void test(int i)
            {
            Fib fib;
            do {
            cout << fib() << endl;
            } while (i--);
            }



  函数对象具有与函数指针类似的行为,同时又能保存自身的一些属性,因此常用于STL通用算法编程。但针对单个的Fibonacci数列项求值,灵活性不如一般的方法。

  希望读者能够从上面的算法分析中举一反三,有所领悟。

参考资料:
  1、Bruce Eckel,Thinking In C++ Volume 2: Practical Programming,机械工业出版社,2006
  2、William J. Collins,Data Structures and the Standard Template Library,机械工业出版社,2003
  3、Knott's Surrey University,The Home page for Fibonacci Numbers and the Golden Section,http://www.mcs.surrey.ac.uk/Personal/R.Knott/Fibonacci/

最优化-斐波那契数列(fibonacci)优化方法 算法原理及代码实现 本文介绍了Fibonacci数列优化的原理,并详细的用pytho实现其算法。 阅读详情

相关推荐

【C语言】斐波那契数列【递归与迭代】

一、背景介绍 二、思路分析 三、代码实现 四、拓展阅读 五、非递归法代码实现

moteandsunlight的博客 2万+

【C语言】斐波那契数列

斐波那契数列是什么?

... 2万+

fibonacci数列C++语言多种实现

转载时请注明出处和作者联系方式 文章出处:http://blog.youkuaiyun.com/chenchong08 作者联系方式:vision_chen@yeah.net 斐波纳契数列(Fibonacci Sequence),又称黄金分割数列,指的是这样一个数列:     1、1、2、3、5、8、13、21、... ... 在数学上,斐波纳契数列以如下被以递归的方法定义:f(0)=1, f(1)

陈冲的博客 1万+

Fibonacci 数列及其计算方法

Fibonacci 数列及其计算方法斐波那契数列(Fibonacci sequence),又称黄金分割数列,这个数列最早是由印度数学家提出来的。不过更多的人学习到这个数列是因为意大利数学家列昂纳多·斐波那契(Leonardoda Fibonacci)和他的《Liber Abaci》一书。在这本书中,列昂纳多·斐波那契以兔子繁殖为例子引出了这个序列,因此这个序列又称为“兔子数列”。 这个序列的前几项

Ivan 的专栏 4万+

Pthread并行编程-以斐波那契数列计算为例

该指的是这样一个数列:1、1、2、3、5、8、13、21、34、……比如数列中的5等于2+3,数列中的13等于5+8。进程是程序的一个动态运行实例。而线程则是在进程的内部(进程的地址空间)运行的一个分支,也是调度的基本单位。其实每次运行上一关的程序,就相当于创建了一个进程,并由于程序中没有创建多个线程,所以该进程中只有一个主线程。本关任务:在串行环境下编写计算斐波那契数列的C语言小程序,并按要求输出对应的斐波那契数列。本关任务:编写使用多线程计算斐波那契数列的C语言小程序,并按要求输出对应的斐波那契数列。

Junds0的博客 1533

swupdate-签名验证

swupdate加密部分具体在中可以查看。

qq_28219531的博客 1148

[CS101] 转载:浅议Fibonacci(斐波纳契)数列求解

原文转载自林健随笔的“浅议Fibonacci(斐波纳契)数列求解” Fibonacci 数列 描述了动物繁殖数量、植物花序变化等自然规律。作为一个经典的数学问题,Fibonacci数列常作为例子出现在程序设计、数据结构与算法等多个相关学科中。 下面简单地分析一下常见的Fibonacci数列求解算法。 递归法 大多数教材在讲解递归算法时总...

weixin_34050005的博客 472

Jupyter Notebook 命名出现“error”且运行后没反应

Jupyter Notebook 命名出现“error”且运行后没反应提前声明错误截图(方便大家看看是不是自己的错误)解决方法 提前声明 我的问题是在看到答主 @开始King的回答后才解决的,因为答主大大的文章后面有些地方不是很详细,我在这里再在King大大的基础上完善一下子 错误截图(方便大家看看是不是自己的错误) 1.命名失败,上面出现一个“error”字样 2.运行失败,无论是点击上方的运行按钮还是按快捷键shift+enter 都只会向下再增加一个代码块,而不会运行程序。 (也不是很多人出现的[*

qq_52770743的博客 1万+

matlab 帕多瓦数列 通项公式_[CS101] 转载:浅议Fibonacci(斐波纳契)数列求解

Fibonacci 数列描述了动物繁殖数量、植物花序变化等自然规律。作为一个经典的数学问题,Fibonacci数列常作为例子出现在程序设计、数据结构与算法等多个相关学科中。下面简单地分析一下常见的Fibonacci数列求解算法。递归法大多数教材在讲解递归算法时总喜欢以Fibonacci数列为例,这是因为我们可以直观地从定义公式的第三行看出Fibonacci数列的递归性。其C++实现如下:unsig...

weixin_34404671的博客 927

从指令到坐标:深度解析307系列基站定位的AT指令实战与排错

本文深度解析了ML307系列模组基站定位的AT指令实战应用与排错方法。重点剖析了AT+MLBSCFG和AT+MLBSLOC两条核心指令的配置、执行流程及异步响应机制,并针对高德与OneOs两种主流定位服务提供了完整的配置指南。文章结合常见错误码(如126、127)和硬件注意事项,分享了确保定位成功的实战经验与稳健的程序框架。

weixin_29057695的博客 487

TI IWR 6843 ISK 毫米波雷达开箱测试

TI IWR6843 ISK毫米波雷达上手体验,教程十分详细,对于新手很友好。

qq_57061492的博客 4033

【递归】_求解_斐波拉契数列

【递归】_求解_斐波拉契数列 斐波纳契数列(Fibonacci sequence)是数学界十分著名的数列。有著名的兔子问题,斐波那契数列又称“兔子数列”、黄金分割数列。这个看上去很简单的数列,却总是出现在人们的眼前。蜻蜓翅膀、蜂巢、菠萝表面的突起等,都是按照这个数列排列的。许多花朵的花瓣数目也具有斐波纳契数列的排列规律,如玫瑰、菊花、向日葵等。 #include <stdio.h> int main(void) { int fun(int); int i,n,count=0; pri

qq_46025307的博客 287

如何在飞腾平台上安装Ubuntu操作系统

注意: 若主板上配置的是NVME硬盘,在进行内核配置时,需要将内核的NEME驱动勾选上,否则移植内核时,无法找到文件系统,进不去操作系统。可以通过rufus软件将镜像做到U盘中,本次使用版本为Rufus 3.9.124 ,其他版本也可以。不要下载live版本的,没有准备网络环境,是一个头疼的事情,笔者暂时没有实现网络安装。将U盘接到主板usb口上,接上串口,显示器,,必需串口有打印才可以安装。可以通过dd命令,将iso安装到U盘。安装的是最小系统,缺少很多命令,需要联网更新,或则更换飞腾专用内核。

技术联盟 2644

leetcode——斐波那契数列的递归和非递归实现

Fibonacci数列 斐波那契数列又称黄金分割数列。因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0,1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递归的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)。 设f(n)...

魔筝炼药师 2294

下拉式菜单设计——Power BI

Power BI导航设计:多级下拉菜单

weixin_41542593的博客 5433

STM32 cubeMX配置串口重定向

这篇文章主要讲解什么是串口重定向,为什么要串口串口重定向。使用printf函数和上位机通信是非常的方便的。希望大家都能够掌握。

m0_49476241的博客 4572

xdoj习题 斐波纳契数列,57Fibonacci数列,数组元素平移,单词排序,字符串复制

问题描述已知一个斐波纳契数列中的数字依次为1, 1, 2, 3, 5, 8, 13, 21, 34, 55 …。请判断该数列中第n个数字(n从1开始计数)是不是素数。输入说明输入一个整数n(1<n<=40)。输出说明判断斐波纳契数列中的第n个数字是不是素数,如果是输出yes,否则输出该数字。输入样例样例1输入6样例2输入4输出样例样例1输出8样例2输出yesint i=0;else。

2301_80300205的博客 785

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

斐波纳契数列 python123

def shulie(n): if n<=2: return 1 else: return shulie(n-1)+shulie(n-2) n=int(input()) c=n for i in range(1,n+1): c=c-1 if c>0: print(shulie(i),end=",") else: print(shulie(i),end="") 求.

ljh5201314hh的博客 8110

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Fibonacci(斐波纳契)数列各种优化解法

Fibonacci数列:   描述了动物繁殖数量、植物花序变化等自然规律。作为一个经典的数学问题,Fibonacci数列常作为例子出现在程序设计、数据结构与算法等多个相关学科中。   下面简单地分析一下常见的Fibonacci数列求解算法。   1、递归法。大多数教材在讲解递归算法时总喜欢以Fibonacci数列为例,这是因为我们可以直观地从定义公式的第三行看出Fibon

xyjikl 1143

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Fibonacci数列 算法

算法——Fibonacci(斐波纳契)序列问题   问题的由来: 13世纪的意大利数学家斐波纳契(Fibonacci)写了一本商用的算术和代数手册Liber abaci>>。在这本书里,他提出了这么一个有趣的问题:假定一对兔子在它们出生整整两个月以后可以生一对小兔子,其后每隔一个月又可以再生一对小兔子。

小兵的专栏 5374

斐波纳契数列【fibonacci】

查找斐波纳契数列中第 N 个数。所谓的斐波纳契数列是指:前2个数是 0 和 1 。第 i 个数是第 i-1 个数和第i-2 个数的和。斐波纳契数列的前10个数字是:0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ...实现两种方式:1。递归:实现相对简单,但递归运行效率低,产生的时间复杂度为指数阶O(2^n),即2的n次方;public class Solution { /...

syc001的专栏 459

一道斐波纳契数列(Fibonacci Sequence)面试题

一道斐波纳契数列(Fibonacci Sequence)面试题 直接上题: 直接上答案: #include &lt;iostream&gt; using namespace std; int main() { int f1 = 1,f2=1,n,i; cin &gt;&gt; n; for(i = 2;i &lt; n;i++) { i...

sessos的博客 486

Python123.io---斐波纳契数列 I

Python123.io---斐波纳契数列 I

liiuyizeliuyize的博客 2736

fibonacci数列-斐波那契数列-python编程

未完待续~ 了解fibonacci数列: 斐波纳契数列(Fibonacci Sequence),又称黄金分割数列。 1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765……(1)fibonacci数列即斐波那契数列,它的特点是前面两个数的和等于后面的一个数,fib(0)=fib(1)=1.(2)斐波那契...

1419
上一篇: 优先级反转 zz
下一篇: 模式匹配的KMP算法详解
发现心流
博客等级 码龄20年 52粉丝 24原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值