C++中实现fibonacci数列的几种方法

目录
  • 前言
  • 一、fibonacci数列是什么?
  • 二、递归实现
    • 1.递归的特点
    • 2.C++实现
  • 三、循环实现
    • 1.C++实现
    • 2.时间复杂度
  • 四、矩阵实现
    • 1.理论推导
    • 2.C++实现
    • 3.时间复杂度

前言

fibonacci数列的实现主要有三种方法:递归、循环与矩阵。这里主要学习了如何在C++中实现这三种方法以及分析它们各自的时间复杂度。

本文参考文章如下:https://www.jb51.net/article/235674.htm

一、fibonacci数列是什么?

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

二、递归实现

1.递归的特点

  • 递归:函数自己调用自己
  • 递归的"缺陷":递归到一定程度,会发生"栈溢出"
  • 递归的"时间复杂度":递归总次数*每次递归的次数
  • 递归的"空间复杂度":递归的深度*每次递归空间的大小(注意:"每次递归空间的大小"是个常数,可以基本忽略不计)
  • 递归的"深度":树的高度(递归的过程是一个"二叉树")

2.C++实现

int main(){
    int n;
    long long sum;  
    
    scanf("%d",&n);
    sum =fb(n);  
    printf("%lld\n",sum);
    
    return 0;
}
 
long long fb(int n){
    if(n<1){
        return 0;
        
    }else if(n==1||n==2){
        return 1;
    }
    return (fb(n-1)+fb(n-2));
}

3.时间复杂度

二叉树的高度是 n - 1,一个高度为k的二叉树最多可以有 2^k - 1个叶子节点,也就是递归过程函数调用的次数,所以时间复杂度为 O(2^n),而空间复杂度就是树的高度 O(n)。

三、循环实现

1.C++实现

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;
}

2.时间复杂度

  • 时间复杂度:O(N)
  • 空间复杂度:O(1)(创建了四个对象,是常数,所以可忽略不计)

四、矩阵实现

1.理论推导

斐波那契数列的递推公式是:f(n)=f(n-1)+f(n-2);

在线性代数中,类似于斐波那契数列这种递推式称为二阶递推式。我们可以用f(n)=af(n-1)+bf(n-2)将二阶递推式一般化。只要符合这种二阶递推式的算法,都可以将算法的时间复杂度降为O(logN)。当然,三阶,四阶....都可以,只要得到递推公式的n阶矩阵即可。如下:

f(n)=af(n-1)+bf(n-2)+......

(f(n),f(n-1))=(f(n-1),f(n-2))*matrix;(matrix是一个矩阵,几阶递推式就是几阶的矩阵,在这里是二阶的矩阵,斐波那契数列属于二阶)

……………………①

………………②

于是只要求得即可。

而类似求还可以简化(快速幂)

例如:

10^68,我们通常是10*10乘上68次,这样时间效率为O(N),我们要用O(logN)方法算:

68的二进制序列为:1000100

10^68=10^64*10^4,也就是取出68二进制序列为1的位,其他忽略。这样我们只算了7次(二进制序列的长度)就可以算出10^68,效率就达到了O(logN)。(最优化算法的关键所在)

所以时间复杂度可以达到最优化O(logN)。

2.C++实现

struct Matrix2By2 {
    Matrix2By2(long long m00 = 0, long long m01 = 0, long long m10 = 0,    long long m11 = 0)
        :m_00(m00), m_01(m01), m_10(m10), m_11(m11) {}
    long long m_00, m_01, m_10, m_11;
};
 
Matrix2By2 MatrixMultiply(const Matrix2By2& matrix1, const Matrix2By2& matrix2) {
    return Matrix2By2(  matrix1.m_00 * matrix2.m_00 + matrix1.m_01 * matrix2.m_10,
                        matrix1.m_00 * matrix2.m_01 + matrix1.m_01 * matrix2.m_11,
                        matrix1.m_10 * matrix2.m_00 + matrix1.m_11 * matrix2.m_10,
                        matrix1.m_10 * matrix2.m_01 + matrix1.m_11 * matrix2.m_11    );
}
 
Matrix2By2 MatrixPower(unsigned int n) {
    assert(n > 0);
    Matrix2By2 matrix;
    if (n == 1)
        matrix = Matrix2By2(1, 1, 1, 0);
    else if (n % 2 == 0) {    // n是偶数
        matrix = MatrixPower(n / 2);
        matrix = MatrixMultiply(matrix, matrix);
    }
    else if (n % 2 == 1) {    // n是奇数
        matrix = MatrixPower((n - 1) / 2);
        matrix = MatrixMultiply(matrix, matrix);
        matrix = MatrixMultiply(matrix, Matrix2By2(1, 1, 1, 0));
    }
    return matrix;
}
 
long long Fibonacci_Solution3(unsigned int n) {
    if (n <= 1) return n;
    Matrix2By2 PowerNMinus2 = MatrixPower(n - 1);
    return PowerNMinus2.m_00;
}

3.时间复杂度

O(logN)。

到此这篇关于C++中实现fibonacci数列的几种方法的文章就介绍到这了,更多相关C++ fibonacci数列内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++项目求Fibonacci数列的参考解答

    [项目:求Fibonacci数列] Fibonacci数列在计算科学.经济学等领域中广泛使用,其特点是:第一.二个数是1,从第3个数开始,每个数是其前两个数之和.据此,这个数列为:1 1 2 3 5 8 13 21 34 55 89 --,请设计程序,输出这个数列,直到这个数字超过10000. [提示]数列可以表示为: [参考解答] #include <iostream> using namespace std; int main( ) { int f1,f2,fn,n; f1=f2=1; n

  • C++中实现fibonacci数列的几种方法

    目录 前言 一.fibonacci数列是什么? 二.递归实现 1.递归的特点 2.C++实现 三.循环实现 1.C++实现 2.时间复杂度 四.矩阵实现 1.理论推导 2.C++实现 3.时间复杂度 前言 fibonacci数列的实现主要有三种方法:递归.循环与矩阵.这里主要学习了如何在C++中实现这三种方法以及分析它们各自的时间复杂度. 本文参考文章如下:https://www.jb51.net/article/235674.htm 一.fibonacci数列是什么? 斐波那契数列(Fibon

  • JavaScript中数组去除重复的三种方法

    废话不多说了,具体方法如下所示: 方法一:返回新数组每个位子类型没变 function outRepeat(a){ var hash=[],arr=[]; for (var i = 0; i < a.length; i++) { hash[a[i]]!=null; if(!hash[a[i]]){ arr.push(a[i]); hash[a[i]]=true; } } console.log(arr); } outRepeat([2,4,4,5,"a","a"

  • JS中动态创建元素的三种方法总结(推荐)

    1.动态创建元素一 document.write() 例如向页面中输出一个 li 标签 <pre class="html" name="code"><span style="font-size:12px;"><script> document.write("<li>123</li>"); </script></span> body标签中就会插入

  • Jquery中ajax提交表单几种方法(get、post两种方法)

    在jquery中ajax提交表单有post与get方式,在使用get方式时我们可以直接使用ajax 序列化表单$( 表单ID) serialize();就行了,下面我来介绍两个提交表单数据的方法.$get方式提交表单get() 方法通过远程HTTP ,下面我来介绍两个提交表单数据的方法. $get方式提交表单 get() 方法通过远程 HTTP GET 请求载入信息 格式 $(selector).get(url,data,success(response,status,xhr),dataType

  • JS 判断某变量是否为某数组中的一个值的3种方法(总结)

    1.正则表达式 js 中判断某个元素是否存在于某个 js 数组中,相当于 PHP 语言中的 in_array 函数. Array.prototype.in_array=function(e){ var r=new RegExp(','+e+','); return (r.test(','+this.join(this.S)+','));}; 用法如下: var arr=new Array(['b',2,'a',4]); arr.in_array('b');//判断'b'字符是否存在于 arr 数

  • 详解node服务器中打开html文件的两种方法

    本文介绍了详解node服务器中打开html文件的两种方法,分享给大家,具体如下: 方法1:利用 Express 托管静态文件,详情查看这里 方法2:使用fs模块提供的readFile方法打开文件,让其以text/html的形式输出. 代码: var express = require('express'); var fs=require("fs"); var app = express(); //方法1:通过express.static访问静态文件,这里访问的是ajax.html //

  • eclipse中自动生成构造函数的两种方法

    eclipse中如何自动生成构造函数 eclipse是一个非常好的IDE,我在写java程序的时候使用eclipse感觉开发效率很高.而且有很多的快捷和简便方式供大家使用,并且能直接生成class文件(不需要javac编译).今天给大家介绍一下如何生成一个类的构造函数. 方法一: 我创建了一个类,里面有两个私有属性age和name.现在构造两个构造函数,一个不带参数,一个带参数.右键->source->Generate Constructors from Superclass,创建一个空参的构

  • 基于Android在布局中动态添加view的两种方法(总结)

    一.说明 添加视图文件的时候有两种方式:1.通过在xml文件定义layout:2.java代码编写 二.前言说明 1.构造xml文件 2.LayoutInflater 提到addview,首先要了解一下LayoutInflater类.这个类最主要的功能就是实现将xml表述的layout转化为View的功能.为了便于理解,我们可以将它与findViewById()作一比较,二者都是实例化某一对象,不同的是findViewById()是找xml布局文件下的具体widget控件实例化,而LayoutI

  • Android中button的onClick事件几种方法

    Android中button的onClick事件几种方法 利用三种方法,学习button的监听事件. 方法一源码如下: package com.example.androidtest; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.view.Menu; import android.widget.Button; import android.

  • 找到整型阵列中最大值和最小值的几种方法总结

    在整型阵列中,我们需要从中获取阵列元素的最大值和最小值: 方法一:先是使用Array进行排序,然后从排序后数组中,最一个元素为最小,最后一个元素为最大. Source Code public static int FindMaxNumber(params int[] stringValue) { Array.Sort(stringValue); return stringValue[stringValue.Length -1]; } public static int FindMinNumber

随机推荐