> 文档中心 > LeetCode 509. 斐波那契数

LeetCode 509. 斐波那契数


一、题目

1、题目描述

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

F(0) = 0,F(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

2、基础框架

  • C++语言 版本给出的基础框架代码如下:
class Solution {public:    int fib(int n) {    }};

3、原题链接

LeetCode 509. 斐波那契数

二、解题报告

1、思路分析

( 1 ) 暴力递归:代码简洁,但是十分低效,以n = 20作出递归树,先算出子问题 f(19) 和 f(18) ,这里需要先计算出 f(19) ,那么需要先计算出 f(18) 和 f(17),这里我们可以看出,f(18) 被计算了两遍

( 2 ) 动态规划 - 重叠子问题:使用一个数组充当备忘录

2、时间复杂度

( 1 )暴力递归: O(2^n);

( 2 )动态规划 - 重叠子问题:O(n)

3、代码详解

class Solution {public:    int fib(int N) {    if (N < 1) return 0;    // 备忘录全初始化为 0    vector<int> memo(N + 1, 0);    // 进行带备忘录的递归    return helper(memo, N);} int helper(vector<int>& memo, int n) {    // base case     if (n == 1 || n == 2) return 1;    // 已经计算过    if (memo[n] != 0) return memo[n];    memo[n] = helper(memo, n - 1) + helper(memo, n - 2);    return memo[n];}};
  • ( 1 ) 一般使用数组充当【备忘录】,当然也可以使用哈希表
  • ( 2 ) 带「备忘录」的递归算法,把⼀棵存在巨量冗余的递归树通过「剪枝」,改造成了⼀幅不存在冗余的递归图,极⼤减少了⼦问题(即递归图中节点)的个数。

三、本题小知识

递归,动态规划