编程学习笔记(LeetCode-509.斐波那契数)

<509> 斐波那契数列

  • 问题重述:
    已知:

\[F(n)= \begin{cases} 0,\qquad \qquad \qquad \qquad \qquad \;\; n=0;\\ 1,\qquad \qquad \qquad \qquad \qquad \;\; n=1;\\ F(n-1)+F(n-2),\qquad n>1,n \in{}N^*;\\ \end{cases} \]

求:\(F(n)\)
其中:\(0\leqslant n \leqslant 30\)

方法一:动态规划+滚动数组

斐波那契数的边界条件是 F(0)=0F(1)=1。当 n>1 时,每一项的和都等于前两项的和,因此有如下递推关系:
F(n)=F(n-1)+F(n-2)

由于 F(n) 只与 F(n-1)F(n-2) 有关,那么就可以采用滚动数组的思想实现:

图1.509.1 滚动数组

C++代码实现:

class Solution {
public:
    int fib(int n) {
        if(n<2){return n;}
        //cur表示当前计算结果,n1和n2表示 n-1, n-2
        int cur, n1, n2;
        cur = 1;
        n1 =  1;
        n2 =  0;
        for(int i = 3; i <= n; i++){
            int temp = n1;
            n2 = n1;
            n1 = cur;
            cur = n1 + n2;
        }
        return cur;
    }
};

方法二:使用通项公式

斐波那契数列 \(F(n)\) 是齐次性递推,根据递推方程:

\[F(n) = F(n-1) + F(n-2) \]

可以写出这样的特征方程:

\[x^2=x+1 \]

求得 \(x_1= \frac{1+\sqrt{5}}{2}\)\(x_2= \frac{1-\sqrt{5}}{2}\) 。设通解为 \(F(n)=c_1x_1^n+c_2x_2^n\) ,代入初始条件\(F(0)=0\)\(F(1)=1\) ,得 \(c_1=\frac{1}{\sqrt{5}}\)\(c_2=-\frac{1}{\sqrt{5}}\) 。因此斐波那契数列的通项公式如下:

\[F(n)=\frac{1}{\sqrt{5}}\left[\left(\frac{1+\sqrt{5}}{2}\right)^n-\left(\frac{1-\sqrt{5}}{2}\right)^n\right] \]

得到通项公式公式后,就可以通过公式直接求解第 \(n\) 项。

  • C++代码实现如下:
class Solution {
public:
    int fib(int n) {
        double sqrt5 = sqrt(5);
        double fibN = pow((1 + sqrt5) / 2, n) - pow((1 - sqrt5) / 2, n);
        return round(fibN / sqrt5);
    }
};
  • 注: 代码中使用的 pow 函数的时空复杂度与CPU支持的指令集相关。



备注: 摘录自LeetCode官方题目解析。

posted on 2021-08-15 14:32  丶LittleBoy  阅读(92)  评论(0)    收藏  举报