斐波拉契数列的递归、非递归、公式法多种方法实现

实现斐波拉契数列:1,1,2,3,5,8...,当n>=3时,f(n)=f(n-1)+f(n-2)。

解:求解斐波拉契数列方法很多,这里提供了4种实现方法和代码,由于第5种数学公式方法代码太过繁琐,只做简单介绍

方法一:递归调用,每次递归的时候有大量重复计算,效率低,可将其调用的过程转化成一颗二叉树进行分析,二叉树的总结点个数不超过(2^n-1)个,由于其是不完全二叉树,那么函数计算的次数必小于(2^n-1),时间复杂度为O(2^n);递归调用的深度为n,空间复杂度为O(n)

方法二:非递归数组方式,循环中仍然有重复计算,时间复杂度为O(n),空间复杂度为O(1)

方法三:非递归循环方式,将前两项的计算结果保存起来,无重复计算,时间复杂度为O(n),空间复杂度为O(1)

方法四:直接利用数学公式法:f(n)={[(1+5^0.5)/2]^n - [(1-5^0.5)/2]^n}/(5^0.5),时间复杂度为O(1),空间复杂度为O(1)

实现代码如下:

#include<iostream>

#include<cmath>

using namespace std;

//方法一:递归调用,有大量重复计算,效率低

long long Fibonacci1(int n)

{

return (n < 2) ? n : Fibonacci1(n - 1) + Fibonacci1(n - 2);

}

//方法二:非递归数组方式,循环中仍然有重复计算

long long Fibonacci2(int n)

{

long long *fibArray = new long long[n + 1];

fibArray[0] = 0;

fibArray[1] = 1;

for (int i = 2; i <= n; i++)

{

fibArray[i] = fibArray[i - 1] + fibArray[i - 2];

}

long long ret = fibArray[n];

delete[] fibArray;

return ret;

}

//方法三:非递归循环方式,将前两项的计算结果保存起来,无重复计算

long long Fibonacci3(int n)

{

long long fibArray[3] = { 0, 1, n };//给fibArray数组赋初值

for (int i = 2; i <= n; i++)

{

fibArray[2] = fibArray[1] + fibArray[0];

fibArray[0] = fibArray[1];

fibArray[1] = fibArray[2];

}

return fibArray[2];

}

//方法四:直接利用数学公式法:f(n)={[(1+5^0.5)/2]^n - [(1-5^0.5)/2]^n}/(5^0.5)

long long Fibonacci4(int n)

{

return (pow((1 + sqrt(5.0)) / 2, n) - pow((1 - sqrt(5.0)) / 2, n)) / sqrt(5.0);

}

//测试代码

int main()

{

int num = 0;

int ret = 0;

cout << "请输入斐波拉契数列的序号:";

cin >> num;

ret = Fibonacci1(num);

/*ret = Fibonacci2(num);*/

/*ret = Fibonacci3(num);*/

/*ret = Fibonacci4(num);*/

cout << ret << endl;

system("pause");

return 0;

}

方法5:生僻的数学公式法

f(n)      f(n-1)        1    1

[                 ] = [          ]^(n-1)

f(n-1)    f(n-2)        1    0

该公式可用数学归纳法进行证明,在矩阵乘法的变换证明过程中,要注意运用斐波拉契数列的性质:后一项为前面两项之和;该数学公式,应用矩阵的乘法,时间复杂度仅为O(log n),时间效率虽然低,但不够实用,源码太过繁琐,参考剑指0ffer面试题9的源码

时间: 2024-12-27 09:26:24

斐波拉契数列的递归、非递归、公式法多种方法实现的相关文章

c语言:写一个函数,输入n,求斐波拉契数列的第n项(5种方法,层层优化)

写一个函数,输入n,求斐波拉契数列的第n项. 斐波拉契数列:1,1,2,3,5,8...,当n大于等于3时,后一项为前面两项之和. 解:方法1:从斐波拉契数列的函数定义角度编程 #include<stdio.h> int fibonacci(int n) { int num1=1, num2=1, num3=0,i; if (n <= 2) { printf("斐波拉契数列的第%d项为:%d\n",n,num1); } else { for (i = 2; i <

【动态规划专题】1:斐波拉契数列问题的递归和动态规划

<程序员代码面试指南--IT名企算法与数据结构题目最优解> 左程云 著 斐波拉契数列问题的递归和动态规划 [题目]:给定整数N,返回斐波拉契数列的第N项.补充问题1:给定整数N,代表台阶数,一次可以跨2个或者1个台阶,返回有多少种走法.补充问题2:假设农场中成熟的母牛每年只会生产1头小母牛,并且永远不会死.第一年农场只有1只成熟的母牛,从第2年开始,母牛开始生产小母牛.每只小母牛3年后成熟又可以生产小母牛.给定整数N,求出N年后牛的数量. [举例]斐波拉契数列f(0)=0, f(1)=1,f(

递归思想之---斐波拉契数列

斐波那契数列中的递归思想 ??如果上述的分析都明白了,那就说明你已掌握了递归,但为了加深对递归的理解,我们再来看一个思考题(来自程序员的数学思考题),题目是这样的,假如动物中有一种特殊的种类,它出生2天后就开始以每天1只的速度繁殖后代.假设第1天,有1只这样的动物(该动物刚出生,从第3天开始繁殖后代).那么到第11天,共有多少只呢? 我们先来按一般顺序思考,先不要考虑第11天,先从第1天开始,看能不能找出规律: [第1天]只有1只动物 [第2天]只有1只动物,还没有繁殖后代,总量为1 [第3天]

C# — 用递归实现斐波拉契数列的第n项

斐波拉契数列:1,1,2,3,5,8,13,21,34,55....... 规律:f(n)=f(n-1)+f(n-2) C# 代码实现: 原文地址:https://www.cnblogs.com/hh8888-log/p/11038915.html

递归1.2用递归函数来实现获取斐波拉契数列中第n个数字的值

用递归函数来实现获取斐波拉契数列中第n个数字的值 ps(斐波那契数列:从3三个数开始,后一个数等于前面两个数的和: 0,1,1,2,3,5,8,13,21,34,55,89,144……) def add(n): if n > 2: return (add(n-1) + add(n-2)) if n == 2: return 1 if n == 1: return 0 b = int(input("请输入一个数字")) print(add(b)) 结果输出: 请输入一个数字10 3

青蛙跳台阶问题-斐波拉契数列

题目1:一个台阶总共有n级,如果一次可以跳1级,也可以跳2级.求总共有多少种跳法 首先我们考虑最简单的情况,加入只有1级台阶,那显然只有一种跳法,如果有2级台阶,那就有两种跳的方法了:一种是分两次跳,每次跳1级:另外一种就是一次跳2级 现在我们来讨论一般情况.我们把n级台阶时的跳法看成是n的函数,记为f(n).当n>2时,第一次跳的时候就有两种不同的选择:一是第一次只跳1级,此时跳法数目等于后面剩下的n-1级台阶的跳法数目,即为f(n-1):另外一种选择是第一次跳2级,此时跳法数目等于后面剩下的

斐波拉契数列的计算方法

面试题9.斐波拉契数列 题目: 输入整数n,求斐波拉契数列第n个数. 思路: 一.递归式算法: 利用f(n) = f(n-1) + f(n-2)的特性来进行递归,代码如下: 代码: long long Fib(unsigned int n) { if(n<=0) return 0; if(n==1) return 1; return Fib(n-1) + Fib(n-2); } 缺陷: 当n比较大时递归非常慢,因为递归过程中存在很多重复计算. 二.改进思路: 应该采用非递归算法,保存之前的计算结

《剑指offer》------斐波拉契数列

题目一:求斐波拉契数列的第n项. 写出一个函数,输入n,求斐波拉契(Fibonacci)数列的第n项.斐波拉契数列定义如下: C++实现: //斐波拉契数列 #include <iostream> using namespace std; //递归实现 long long Fibonacci1(unsigned int n){ if(n<=1){ return n; } return Fibonacci1(n-1)+Fibonacci1(n-2); } //非递归实现 long long

Fibonacci斐波拉契数列----------动态规划DP

n==10 20 30 40 50 46 体验一下,感受一下,运行时间 #include <stdio.h>int fib(int n){ if (n<=1)     return 1; else            return fib(n-1)+fib(n-2); }int main( ){ int n; scanf("%d",&n); printf("%d\n" ,fib(n) );} 先 n==10 20 30 40 50 46