Algorithm2——斐波那契数列

来源:互联网 发布:淘宝宝贝编辑用什么 编辑:程序博客网 时间:2024/04/29 17:58

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

问题: 求Fibonacci第n项?

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

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

参考链接如下:

  • fibonacci 维基百科
  • 知乎王希——关于斐波那契数列的回答
  • Gocalf blog——计算斐波纳契数,分析算法复杂度
  • 快速幂 百度百科

1 递归

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

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

2 公式法

维基百科公式

//! calculate by formularint 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 methodint 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^nvoid 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^ntemplate <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^ntemplate <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 onceclass 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;};
原创粉丝点击