草庐IT

斐波那契数列

龙星尘 2024-02-05 原文

目录

斐波那契数列是什么?

第一种解法(递归法):

C++递归法求斐波那契数列:

第一种解法的效率:

第二种解法(记忆化递归/动态规划):

C++记忆化递归/动态规划求斐波那契数列:

第二种解法的效率:

第三种解法(递推):

C++递推解法:

第三种解法的效率:

总结:


斐波那契数列是什么?

一、斐波那契数列指的是这样一个数列:1、1、2、3、5、8、13、21、…… 这个数列从第三项开始,每一项都等于前两项之和。

二、应用:通常在个别股票中不是太准确,通常在指数上有用。当市场行情处于重要关键变盘时间区域时,这些数字可以确定具体的变盘时间。使用斐波那契数列时可以由市场中某个重要的阶段变盘点向未来市场推算,到达时间时市场发生方向变化的概率较大。

第一种解法(递归法):

  利用C++求解斐波那契数列第N项数字是什么?我们可以用C++算法,递归法来进行表示.我们知道,斐波那契数列的每一项数字都等于前面两项数字之和,那么用计算机函数来表示,若fun为求斐波那契数列的第N项的函数,那么fun(N)=fun(N-1)+fun(N-2).

  而且我们知道,斐波那契数列数列的第一项和第二项都为1,但是我们在算fun(2)的时候,需要fun(1)+fun(0).第一项数字为1是肯定的,那第0项数字呢?我们就将它姑且当作为0,也可以解决这个问题!

C++递归法求斐波那契数列:

#include<bits/stdc++.h> //万能头文件 
using namespace std; //批准使用std 
int fun(int n){ //递归函数,求斐波那契数列的第N项数字 
	if(n==0) //如果是第0项数字 
	  return 0; //返回0 
	if(n==1) //如果求第一项数字 
	  return 1; //返回1 
	return fun(n-1)+fun(n-2); //进行递归式调用 
}
int main(){ //主函数 
	while(1){ //无限循环输入 
		int n; //定义整数,代表斐波那契数列的第n项数字 
		cin>>n; //输入n 
		cout<<fun(n)<<endl; //输出斐波那契数列的第n项数字的值		
	}
	return 0; //结束 
}

第一种解法的效率:

fun(n)=

fun(n-1)=     fun(n-2)=

fun(n-1-1)=   fun(n-1-2)=   fun(n-2-1)=  fun(n-2-2)=

.........................................................................................................................

fun(2)=                   ............................................

fun(1)=1        fun(0)=0            .................................................

  最后得出结论,第一种解法普通递归法的时间复杂度为O(2^n).时间复杂度实在是太大了,虽然这样写代码很简短,比其他两种算法都短,但是由于时间效率太慢,不建议使用!

第二种解法(记忆化递归/动态规划):

 第一种普通递归法为什么那么的慢呢?那是因为它重复计算了很多个以前早就已经计算过的值,相当于重复计算,所以时间非常的慢.我们要怎么优化呢?当然是避免重复运算了!怎么避免呢?自然是将我们计算过的值存下来,第二次还需要这个值的时候不需要计算了,直接把之前存下来的那个值返回回去就可以了!

  我们刚开始,需要进行初始化,就是将这个记录所有需要计算的值的这个数组初始化(第i个下标的值代表斐波那契数列的第i项数字的值),初始化为-1!为什么呢?这样体现了做标记的作用,代表这个下标所存的斐波那契数列的第i项数字的值还没有算过.这样在递归过程中,如果是-1,代表没有算过,进行赋值,如果算过来,不需要递归重复计算了,直接将这个的值返回回去就可以了!

  因为我们知道斐波那契数列的第一项和第二项是什么,所以在最开始就要进行赋值f[0]=0(第0项自然为0)f[1]=1;f[2]=1;然后就可以进行递归了!

  这种算法既可以称为"记忆化递归"(毕竟将算过的东西存起来,就是记录下来了),它还有一个名字,是一种很通用的算法"动态规划"!

C++记忆化递归/动态规划求斐波那契数列:

#include<bits/stdc++.h>  //万能头文件 
using namespace std; //允许使用std里面的函数及类 
long long f[5000000]; //记忆化的数组 
long long fun(int n){ //求斐波那契数列的第n项数字 
	if(n==0) //如果是第0项 
	  return 0; //返回值为0 
	if(n==1) //如果求第一项 
	  return 1; //那么返回值为1 
	if(f[n]==-1) //如果这个值没有计算过 
	  f[n]=fun(n-1)+fun(n-2); //进行递归存储计算 
	return f[n]; //计算过的话就直接返回 
}
int main(){ //主函数 
	memset(f,-1,sizeof(f)); //将f这个数组里面的每一个值赋值为-1 
	f[0]=0; //将第0项赋值为0 
	f[1]=1; //将第1项赋值为1 
	f[2]=1; //将第2项赋值为1 
	while(1){ //无限循环输入 
  		int n; //定义整数,代表斐波那契数列的第n项数字 
    	cin>>n; //输入n 
    	cout<<fun(n)<<endl;	//利用记忆化递归/动态规划算法函数求斐波那契数列的第n项数字的值	
	}
    return 0; //结束 
}

第二种解法的效率:

 将每一个所计算出来的值记录下来,时间复杂度为O(N^2).已经算是非常快的了!比之前的普通递归快了很多倍了!

第三种解法(递推):

  我们在第二种解法中已经看到,可以将值存起来进行计算,不过第二种方法是自上而下来进行计算,和第一种普通递归一样,不过省略了重复的计算步骤.

  而我们第三种解法,是自下而上计算:

  我们都知道,第一个数为1,第二个数也为1,可以存入数组f里面,那么f[3]是不是等于f[1]+f[2]=2了呢?算出了f[3],f[4]就等于f[2]+f[3]=3了!

  这样自下而上计算非常的简洁迅速,快到了极点,堪称斐波那契数列最快的算法之一了.

C++递推解法:

#include<bits/stdc++.h> //万能头文件 
using namespace std; //允许使用std里面的函数及类 
long long f[5000000]; //记忆化的数组
int main(){ //主函数 
    long long n; //定义整数,代表斐波那契数列的第n项数字 
    f[1]=f[2]=1; //将斐波那契数列的第一项和第二项初始化为1 
    cin>>n; //输入n 
    for(long long i=3;i<=n;i++) //从第三项开始自下而上计算 
      f[i]=f[i-2]+f[i-1]; //f[i-2]和f[i-1]的值绝对是算出来了的 
    cout<<f[n]<<endl;// 输出数组下标为n的值 
    return 0; //结束 
}

第三种解法的效率:

  快,非常快,快到无与伦比!只有O(N)的时间复杂度(无论斐波那契数列的多少项,都可以很快算出来,当然要配上一个高精度),而且代码是如此的简短! 

总结:

  对于求斐波那契数列的算法中,最快的是递推解法O(n),最慢的就是普通递归法O(2^n).所以建议大家以后尽量用一些高效又简洁的算法来解决问题!

有关斐波那契数列的更多相关文章

  1. Ruby 斐波那契算法 - 2

    下面是我写的一个计算斐波那契数列中的值的方法:deffib(n)ifn==0return0endifn==1return1endifn>=2returnfib(n-1)+(fib(n-2))endend它工作到n=14,但在那之后我收到一条消息说程序响应时间太长(我正在使用repl.it)。有人知道为什么会这样吗? 最佳答案 Naivefibonacci进行了大量的重复计算-在fib(14)fib(4)中计算了很多次。您可以将内存添加到您的算法中以使其更快:deffib(n,memo={})ifn==0||n==1returnnen

  2. 【第37天】斐波那契数列与爬楼梯 | 迭代的鼻祖,递推与记忆化 - 2

    本文已收录于专栏?《Java入门一百例》?学习指引序、专栏前言一、递推与记忆化二、【例题1】1、题目描述2、解题思路3、模板代码4、代码解析5.原题链接三、【例题1】1、题目描述2.解题思路3、模板代码4、代码解析5、原题链接三、推荐专栏四、课后习题序、专栏前言  本专栏开启,目的在于帮助大家更好的掌握学习Java,特别是一些Java学习

  3. ruby - Ruby 中的斐波那契数列(递归) - 2

    我正在尝试实现以下功能,但它一直给我stackleveltoodeep(SystemStackError)错误。任何想法可能是什么问题?deffibonacci(n)[n]if(0..1).include?n(fibonacci(n-1)+fibonacci(n-2))ifn>1endputsfibonacci(5) 最佳答案 试试这个deffibonacci(n)returnnif(0..1).include?n(fibonacci(n-1)+fibonacci(n-2))endputsfibonacci(5)#=>5也检查这篇文

  4. ruby - 斐波那契线 - 2

    我正在尝试解决来自ProjectEuler的问题在Ruby单行代码中,我很好奇questiontwo是否有更优雅的解决方案:EachnewtermintheFibonaccisequenceisgeneratedbyaddingtheprevioustwoterms.Bystartingwith1and2,thefirst10termswillbe:1,2,3,5,8,13,21,34,55,89,...ByconsideringthetermsintheFibonaccisequencewhosevaluesdonotexceedfourmillion,findthesumofthe

  5. javascript - 坚持使用 Javascript 的简单斐波那契数列 - 2

    我似乎不明白这段代码的输出:functionfib(x){return(x===0||x===1)?x:fib(x-1)+fib(x-2);}fib(7);//outputis13这是我的思考过程:将int传递给函数并检查它是0还是1如果为0或1,则继续返回传递的值如果不是0或1,则7减1,然后7减2返回根据我(显然是错误的)想法的输出是11函数如何得出13的结果? 最佳答案 --------------------------------------------------------------|Step|Function|Re

  6. javascript - JavaScript 中的斐波那契数列 - 2

    functionfib(n){constresult=[0,1];for(vari=2;i上面代码的输出是13。我不明白for循环部分。在第一次迭代中i=2,但在第二次迭代之后i=3所以a=2和b=1和第三次迭代i=4所以a=3,b=2,依此类推...如果继续进行最终序列将是:[0,1,1,3,5,7,9,11],这是不正确的。正确的顺序是[0,1,1,2,3,5,8,13] 最佳答案 Youwerenotusingtheprevioustwonumbersthatarealreadyinthearrayto>generatethe

  7. javascript - 斐波那契数列 - 计算位数 - JavaScript - 2

    所以,我已经成功地编写了斐波那契数列来创建一个包含数字序列的数组,但是我需要知道长度(有多少位数字)第500个数字有。我试过下面的代码,但它找到了科学记数法的长度(22位),而不是它应该返回的正确的105。关于如何将科学记数法数字转换为实际整数有什么想法吗?varfiblength=functionfiblength(nth){vartemparr=[0,1];for(vari=2;i 最佳答案 为什么不使用将数字除以10直到数字小于1的简单过程。像这样简单的东西应该可以工作(递归defobv也可以)functiongetDigit

  8. java - 在 Java 8 中使用 Memoized 的无限斐波那契数列 - 2

    首先,我是一名JavaScript程序员,对Java8还很陌生,正在尝试新的功能特性。由于我精通JS编码,所以我实现了自己的JS惰性函数库以进行概念验证。https://github.com/kenokabe/spacetime使用该库,我可以编写无限自然数和斐波那契数列,如下所示:JavaScriptvarspacetime=require('./spacetime');var_=spacetime.lazy();varnatural=_(function(n)//memoizedautomatically{returnn;//Naturalnumbersisdefinedasthe

  9. javascript - 斐波那契数列 (JS) - 偶数之和 - 2

    我开始了欧拉计划。我在问题2上想出了这个代码来计算高达400万的偶数斐波那契数的总和。代码似乎做了很多我想做的事。运行代码时,我确实看到列出了正确的总和。我真正感到困惑的唯一部分是结果中显示的最后一个数字。这是它显示的内容:JS代码:varprevious=0;varcurrent=1;varsum=0;varnext;for(i=1;i结果:210441887983382143286069625711410891544613732(thisisthenumberiwastryingtoget)=>354224848179262000000(confusedastowhythisnum

  10. JavaScript:计算斐波那契数列值<10000中所有偶数的总和 - 2

    我必须完成这个练习,但我没有得到我需要的结果。规范是:计算斐波那契数列中小于10,000的所有偶数的总和。前几个数字的总和为:2、8、34、144、610。我有一个产生此输出的fiddle:10,44,188,798,3382。varx=1;vary=2;varsum=0;varlimit=10000;varevensum=2;while((x+y)fiddlelink有人可以帮我找出我缺少的部分来完成这个练习吗?非常感谢。更新感谢所有发布解决方案的人。他们都工作得很好。 最佳答案 您正在打印偶数的总和。如果您想记录每个偶数fib数

随机推荐