实验2:斐波那契数计算

1.实验目的

掌握分冶策略的基本思想,用分冶法解决问题的一般技巧。

2.实验内容

参见本实验配套课件pdf文档,实现斐波那契数f(n)的三种算法:(1) 基于定义的递归算法; (2)动态规划(迭代算法);(3)分治算法(非递归版本)的实现。

3.实验要求

编制程序并对其时间复杂度和空间复杂度进行分析。测试随着 n 增加各个算法实现的实际运行时间 。

\square 基础性实验 \square 综合性实验 \boxtimes 设计性实验

实验报告正文

一、问题分析(模型、算法设计和正确性证明等)

  1. 基于定义的递归算法

  2.  

    根据Fibonacci定义可得递归表达式:

    $$
    Fib(n)=\left\{ \begin{array}{ll} 0, & {if \quad n=0}\\ 1, & {if \quad n=1}\\ Fib(n-2) + Fib(n-1), & {if \quad n\geq2} \end{array} \right.
    $$

  3. 动态规划(迭代算法)

  4.  

    先解决小规模问题,并讲解保存起来,利用小规模问题的解构造更大规模问题的解。

    当n=0或n=1时,直接返回n;

    当n \geq 2时从0,1开始递推计算结果。

  5. 分治算法(非递归)

  6.  

    根据Fibonacci定义可构造如下等式

    $$
    \left\{ \begin{array}{ll} Fib(2)=Fib(1)+Fib(0)\\ Fib(1) = Fib(1) \end{array} \right.
    $$

     

    使用二维矩阵表示上述关系

    $$
    \left[ \begin{matrix} Fib(2) \\ Fib(1) \end{matrix} \right]= \left[ \begin{matrix} 1 & 1\\ 1 & 0 \end{matrix} \right]\times \left[ \begin{matrix} Fib(1)\\ Fib(0) \end{matrix} \right]
    $$

     

    将上式推广,则有

    $$
    \left[ \begin{matrix} Fib(n) \\ Fib({n-1}) \end{matrix} \right]= \left[ \begin{matrix} 1 & 1\\ 1 & 0 \end{matrix} \right]^{n-1}\times \left[ \begin{matrix} Fib(1)\\ Fib(0) \end{matrix} \right]= \left[ \begin{matrix} 1 & 1\\ 1 & 0 \end{matrix} \right]^{n-1}\times \left[ \begin{matrix} 1\\ 0 \end{matrix} \right]
    $$

     

    要求解的Fib(n)​即为向量\left[ \begin{matrix} Fib(n) \\ Fib({n-1}) \end{matrix} \right]的第一个分量。

二、算法设计复杂度分析(伪代码,不要粘贴源码)

  1. 基于定义的递归算法

    下求解递归算法时间复杂度下求解递归算法的时间复杂度,设规模为n问题所需的计算时间为T(n),则有:

    $$
    T(n)=\left\{ \begin{array}{ll} O(1), & {if \quad n=1||n=0}\\ T(n-2) + T(n-1), & {if \quad n>2} \end{array} \right.
    $$

     

    通过微分方程法求得方程的解:

    $$
    T(n) \in \theta(Fib(n))=\theta(\frac{1}{\sqrt{5}}(\frac{1+\sqrt5}{2})^n-\frac{1}{\sqrt 5}(\frac{1-\sqrt{5}}{2})^n)
    $$

     

    下讨论递归算法的空间复杂度,每次返回函数本身都会开辟新的栈空间,故递归树的高度即为该算法所用空间。递归出口为1和0,递归树高度为n,所以空间复杂度为\theta (n)。

  2. 动态规划(迭代算法)

    下讨论动态规划算法的时间复杂度,设规模为n的问题所需的计算时间为T(n),则有:

    $$
    T(n)\in \theta(n-1)=\theta(n)
    $$

     

    下讨论动态规划算法的空间复杂度,该算法仅使用两个整型变量(伪代码中a,b)辅助运算,故空间复杂度为\theta(1),或称in place。

  3. 分治算法(非递归)

    下讨论分治算法的时间复杂度,其中矩阵乘法T_{2\times2}\times T_{2\times2}T_{2\times 2}\times R_{2\times 1}时间复杂度均为O(1)。

    设规模为n的问题所需的计算时间为T(n),则有时间复杂度递归表达:

    $$
    T(n)=\left\{ \begin{array}{ll} O(1) & {if\quad n=1}\\ T(n/2)+O(1) & {if\quad n>1} \end{array} \right.
    $$

     

    $$
    \therefore T(n)\in \theta(log_2n)
    $$

     

    考虑该算法空间复杂度,仅使用两个固定大小的矩阵(数组)辅助运算,故空间复杂度为\theta(1),或称in place。

三、实验结果记录和分析(测试向量上的测试结果、运行时间)

三种算法结果一致,以下显示部分运行结果,其中递归算法在有限时间内(10s)只能计算n\leq46的结果。

Fibonacci位数Fibonacci数
11
68
1189
16987
2110946
26121393
311346269
3614930352
41165580141
70117669030460994
8014472334024676220
  1. 基于定义的递归算法

    Fibonacci位数运行时间(ms)
    10.0002
    60.0001
    110.0006
    160.0055
    210.0594
    260.6619
    317.3609
    3683.4256
    41922.788
    4610249.3
    51113661
  2.  

  3. 动态规划(迭代算法)

    Fibonacci位数运行时间(ms)
    10.0003
    100.0001
    1000.0002
    10000.0017
    100000.0163
    1000000.1632
    10000001.7389
    1000000017.2346
    100000000170.5181
    10000000001722.873

 

  1. 分治算法(非递归)

    Fibonacci位数运行时间(ms)
    10.0003
    100.0004
    1000.0004
    10000.0005
    100000.0007
    1000000.0008
    10000000.001
    100000000.001
    1000000000.0012
    10000000000.0013

 

四、总结(可描述出现的问题和解决方法、经验和反思等)

在本实验中,分治算法运算时间较快,\theta(log_2n)的复杂度随问题规模增加,运行时间变化较小,难以测量。因此本实验选择运算速率相对较慢的python语言运行相同程序,得到结果相对易于测量观察。

本实验中,通过不断对求解斐波那契数的算法进行优化,我总结如下:

  1. 递归是方便的算法,编写程序只需考虑求解问题的一部分或是小规模问题,即可运算得到正确结果,无需考虑具体计算过程。但是递归树节点的大量重复很难避免,于是考虑运算过后将小问题的结果储存,求解大问题时直接取出计算。这个过程类似动态的设置递归出口,即不断增加递归出口,从而达到给递归树剪枝的目的来避免重复计算或是每次递归到底层出口,而代价是辅助空间需要相应增加(本实验相对特殊,由于Fibonacci数的特性几乎无需辅助空间)。当递归算法完全转化为“动态设置递归出口”的算法后,不妨从最开始的递归出口考虑问题,将求解大问题需要的小问题答案提前计算储存,即动态规划算法。

  2. 分治算法在本实验中主要体现在矩阵快速幂,矩阵的使用将Fibonacci数的计算方法完全转化为数学表达,且避开了通项公式中程序不擅长的小数计算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值