力扣|力扣 - 剑指 Offer 10- I. 斐波那契数列
题目
剑指 Offer 10- I. 斐波那契数列
思路1(递归 / 自顶向下)
- 这题是很常见的一道入门递归题,可以采用自顶向下的递归方法,比如我们要求第
n
个位置的值,根据斐波那契数列的定义fib(n) = fib(n-1) + fib(n-2)
,即等于前一个和前前一个两个的值之和
- 但是如果直接递归,会导致很多重复的计算,效率很低,比如
n
为 5 时:
-
fib(5)
为fib(4)
和fib(3)
两个值之和
- 然后
fib(4)
又等于fib(3)
和fib(2)
两个值之和。注意,fib(3)
在上一步已经求过了,这里还要再求一次
- 另一个
fib(3)
即为fib(2)
和fib(1)
两个值之和,同样,fib(2)
,也被求过了
- ……
文章图片
-
- 【力扣|力扣 - 剑指 Offer 10- I. 斐波那契数列】根据上面例子我们可以发现这样子会导致很多多余的计算,做无用功,也会出现由于
n
的增大导致计算量急剧增大。因此我们可以将这个算法优化一下,就是添加一个表格memory
来记录计算过的值,在每次递归的时候,判断一下之前是否计算过了,如果发现计算过了,直接返回数组中对应的值,否则就计算一下,然后记录到memory
表格里
class Solution {int[] memory;
public int fib(int n) {
memory = new int[n+1];
return help(n);
}public int help(int n) {
// 递归结束的条件
if (n <= 1) {
return n;
}// 判断是否计算过了
if (memory[n] != 0) {
return memory[n];
}// 没有在 memory 中找到就计算一下,然后在记录到 memory 中
int i = help(n - 1) + help(n - 2);
i %= 1000000007;
memory[n] = i;
return memory[n];
}
}
复杂度分析
- 时间复杂度:\(O(N)\)
- 空间复杂度:\(O(N)\)
- 同样,根据斐波那契数列定义,可以发现第
n
个的值为前两个值之和,因此我们可以从第一个开始计算,循环计算到n
就得到了结果,空间上仅仅占两个变量的空间,为 \(O(1)\) ,代码如下:
class Solution {
public int fib(int n) {
if (n < 2) {
return n;
}int a = 1;
int b = 1;
for (int i = 2;
i < n;
i++) {
int temp = (a + b);
a = b;
b = temp;
b %= 1000000007;
}return b;
}
}
复杂度分析
- 时间复杂度:\(O(N)\)
- 空间复杂度:\(O(1)\)
推荐阅读
- 剑指|剑指 Offer 13. 机器人的运动范围(dfs,bfs)
- 数据结构与算法|【算法】力扣第 266场周赛
- leetcode|今天开始记录自己的力扣之路
- 剑指offer60.n个骰子的点数
- 剑指offer——最小的K个数
- Android|年后备战金三银四(Android面试吃透这一篇就没有拿不到的offer......)
- 剑指黄昏
- 剑指offer15.二进制中1的个数
- java|阿里工作8年,肝到P8就剩这份学习笔记了,已助朋友拿到10个Offer
- 字节前端面试经验(已拿到offer)