509. 斐波那契数

169 阅读2分钟

[509. 斐波那契数]

「这是我参与2022首次更文挑战的第30天,活动详情查看:2022首次更文挑战」。

题目描述

斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:

F(0) = 0F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1

给定 n ,请计算 F(n) 。

示例

示例1 :

输入: n = 2
输出: 1
解释: F(2) = F(1) + F(0) = 1 + 0 = 1

示例 2:

输入: n = 3
输出: 2
解释: F(3) = F(2) + F(1) = 1 + 1 = 2

示例 3:

输入: n = 4
输出: 3
解释: F(4) = F(3) + F(2) = 2 + 1 = 3

提示:

  • 0 <= n <= 30

思路

这可以说是年轻人的第一道动态规划题。判定一道题使用动态规划的标准是看当前状态是否依赖之前的状态,即问题由许多重复的子问题组成,判定为是之后有以下几个步骤,复习一下:

  1. 确定dp数组(dp table)以及下标的含义

  2. 确定递推公式

  3. dp数组如何初始化

  4. 确定遍历顺序

  5. 举例推导dp数组

而这道题直接给出了递推公式,具体到这道题:

1、dp数组含义:即 f(n)

2、F(n) = F(n - 1) + F(n - 2),其中 n > 1;

3 、F(0) = 0,F(1) = 1

4、依赖之前的状态,即从前往后遍历。

5、 0,1,2,3,5,8···

但是,在一开始学习编程语言的时候,常常是使用递归,也就是回溯的做法,使用递归的一般步骤:

  1. 确定递归函数的返回值以及参数

  2. 明确回溯函数终止条件

  3. 寻找单层搜索的过程

具体到这道题:

1、 返回值和参数:很明显题目给好了

2、 终止条件: 因为 F(0) = 0,F(1) = 1,使用当为0或1时,就需要返回。

3、单层搜素:由F(n) = F(n - 1) + F(n - 2),其中 n > 1知;需要进入F(n - 1) 和 F(n - 2) 。

代码实现

动态规划由于只是依赖前两个状态,所以可以压缩dp数组的大小

class Solution {
public:
    int fib(int N) {
        if (N <= 1) return N;
        vector<int> dp(N + 1);
        dp[0] = 0;
        dp[1] = 1;
        for (int i = 2; i <= N; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[N];
    }
};

递归:

class Solution {
public:
    int fib(int N) {
        if (N <= 1) return N;           //终止条件
        return fib(N-1)+fib(N-2);      //单层搜索
    }
};

总结

简要的介绍和复习了动态规划和回溯。