【力扣】509. 斐波那契数

题目链接:https://s.heyiqi.cc/w7l

题目描述

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

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

给你n,请计算F(n)

示例 1:

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

示例 2:

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

示例 3:

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

0 <= n <= 30


方法一:递归

暴力递归

由题目得知F(n)是由F(n-1)和F(n-2)构成,而F(0)=0,F(1)=1,因此终止条件为n<2,返回0或1(与n的值一致)。

1
2
3
4
5
6
7
class Solution {
public:
int fib(int n) {
if(n < 2) return n;
return fib(n - 1) + fib(n - 2);
}
};

时间复杂度:O(2^n)

空间复杂度:O(1)

带备忘录的递归

设置一个全局变量memo,保存已经计算过的子问题答案,碰到相同的问题时直接返回,也就是所谓的“剪枝”。

unordered_map是C++中的哈希表
count方法返回表中有多少个key,由于哈希表不能重复,因此只会返回01
访问memo[key]不存在时会自动创建

1
2
3
4
5
6
7
8
9
10
class Solution {
unordered_map<int,int> memo;
public:
int fib(int n) {
if(memo.count(n)) return memo[n];
if(n < 2) return n;
memo[n] = fib(n - 1) + fib(n - 2);
return memo[n];
}
};

时间复杂度:O(N)

空间复杂度:O(1)

方法二:动态规划

DP数组

创建一个dp数组,dp[0]=0dp[1]=1dp[n]=dp[n-1]+dp[n-2]dp[n]即答案。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public:
int fib(int n) {
if(n < 2) return n;
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];
}
};

时间复杂度:O(N)

空间复杂度:O(N)

滚动数组

0 1 2 3 4 5 6 7
val 0 1 1 2 3 5 8 13

在计算DP数组的时候,可以发现第n项只与n-1项和n-2项有关,因此我们无需保存n-3及之前的项,将空间复杂度优化到O(1)。

first为第1项,second为第2项,计算第3项时,t=first+second,然后first改为第2项的值,second改为第3项的值。second始终是最后一项,即要求的答案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public:
int fib(int n) {
if(n < 2) return n;
int first = 0;
int second = 1;
for(int i=1;i<n;i++){
int t = first + second;
first = second;
second = t;
}
return second;
}
};

时间复杂度:O(N)

空间复杂度:O(1)


【力扣】509. 斐波那契数
https://heyq.cc/2021/09/08/leetcode-509/
作者
YiQi He
发布于
2021年9月8日
许可协议