Algorithm2——斐波那契数列

本系列算法实现都是在学习数据结构(C++语言版),清华大学邓俊辉教授编,听邓老师edX网课过程中自己实现的例子。

问题: 求Fibonacci第n项?

解决: 用以下四种种方法实现。

  • 递归
  • 公式法
  • 动态规划
  • 矩阵

参考链接如下:

1 递归

递归最简单,但是算法复杂度高,为O(2^n)

//! usual recursion
// 0 1 2 3 5 8
int fib_recursion(int n)
{
    return n < 2 ? n : fib_recursion(n - 1) + fib_recursion(n - 2);
}

2 公式法

维基百科公式

//! calculate by formular
int fib_formular(int n)
{
    const double constant_a = (1 + sqrt(5)) / 2;
    const double constant_b = (1 - sqrt(5)) / 2;
    const double constant_c = sqrt(5) / 5;

    return constant_c * (fast_pow_iterate(constant_a, n) - fast_pow_iterate(constant_b, n));
}

3 动态规划

有两种实现方法,基本思想是DP,动态规划包含内容很多,可以专门学习下。

//! dynamic programming (DP)
int fib_dynamic_programming_n(int n)
{
    std::vector<int> a(n + 1);

    for (int i = 0; i < n + 1; ++i)
    {
        i < 2 ? a[i] = i : a[i] = a[i - 1] + a[i - 2];
    }

    return a[n];
}

//! dynamic programming (DP)
int fib_dynamic_programming_3(int n)
{
    int cur = 1, pre = 0;

    //base
    if (n < 2)
        return n;

    //iterator n-1
    while (--n)
    {
        cur = cur + pre;
        pre = cur - pre;
    }
    return cur;
}

4 矩阵

递推公式如下,

公式推导见fibonacci 维基百科Gocalf blog——计算斐波纳契数,分析算法复杂度

#include <eigen3/Eigen/Eigen>

//! matrix method
int fib_matrix(int n)
{
    Eigen::Matrix2i r;
    Eigen::Matrix2i base;

    base << 1, 1, 1, 0;
    fast_pow_matrix(base, n, r);
    return r(0, 1);
}

其中关于快速求解矩阵幂使用的是以下算法

#include <eigen3/Eigen/Eigen>

//! solve matrix^n
void fast_pow_matrix(Eigen::Matrix2i& base, int n, Eigen::Matrix2i& r)
{
    r << 1, 0, 0, 1;

    while (n > 0)
    {
        if (n & 1)
            r *= base;
        base *= base;
        n >>= 1;//n=n/2
    }
}

其实用到的算法和求单个数字的快速幂是一样的,算法如下,有两种方法,分别是迭代和递归。

//! solve base^n
template <typename T>
T fast_pow_iterate(T base, int n)
{
    T r = 1;
    while (n > 0)
    {
        if (n & 1)
            r *= base;
        base *= base;
        n >>= 1;//n=n/2
    }
    return r;
}

//! solve base^n
template <typename T>
T fast_pow_recursion(T base, int n)
{
    //recursion base
    if (n == 1)
        return base;

    T tmp = fast_pow_recursion(base, n >> 1);
    return (n % 2 ? base : 1) * tmp * tmp;
}

5 根据动态规划实现的一个Fibonacci类

#pragma once


class Fibonacci
{
public:
    Fibonacci(int n_): fibn(n_)
    {
        cur = 1, pre = 0;

        //iterator n-1
        while (--n_)
        {
            cur = cur + pre;
            pre = cur - pre;
        }
    }
    ~Fibonacci(){};

    void reset_fib(int n_)
    {
        while (n_ != fibn)
        {
            n_<fibn?get_pre():get_next();
        }
    }

    int get_fibn()
    {
        return fibn;
    }

    int get_cur()
    {
        return cur;
    }

    int get_pre()
    {
        fibn--;
        pre = cur - pre;
        cur = cur - pre;
        return cur;
    }

    int get_next()
    {
        fibn++;
        cur = cur + pre;
        pre = cur - pre;
        return cur;
    }

private:
    int fibn; //record n
    int cur;
    int pre;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值