这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战
题目
斐波那契数,通常用 F(n)
表示,形成的序列称为 斐波那契数列 。该数列由 0
和 1
开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
给你 n
,请计算 F(n)
。
示例
输入: 2
输出: 1
解释: F(2) = F(1) + F(0) = 1 + 0 = 1
输入: 3
输出: 2
解释: F(3) = F(2) + F(1) = 1 + 1 = 2
输入: 4
输出: 3
解释: F(4) = F(3) + F(2) = 2 + 1 = 3
提示
0 <= n <= 30
解题思路
根据题目可以得出,从数值2
开始,每一个数字都是由前面两位数字相加的和。那么,我们这里就可以得到两种解题方式:
- 自顶向下:从
F(n)
出发,往0
的方向延申
- 自底向上:从
0
出发,推导到F(n)
代码实现
方式一:递归
class Solution {
public int fib(int n) {
// 边界判断
if(n < 2){
return n;
}
// 向下递归,得到最终结果
return fib(n - 1) + fib(n - 2);
}
}
方式二:递归优化
方法一虽然简单,不过在递归的过程中会产生多次重复的计算,这里我们可以使用一个Map来保存每一次的计算结果,当遇上已经计算过的数值,则直接从Map中取出返回即可。
class Solution {
private Map<Integer, Integer> map = new HashMap<>();
public int fib(int n) {
// 边界判断
if(n < 2){
return n;
}
// 判断当前数值是否递归过,如果是,则直接返回结果
if(map.containsKey(n)){
return map.get(n);
}
// 向下递归,得到最终结果
int sum = fib(n - 1) + fib(n - 2);
// 保存结果
map.put(n, sum);
return sum;
}
}
方式三:动态规格
class Solution {
public int fib(int n) {
// 边界判断
if(n < 2){
return n;
}
int[] dp = new int[n + 1];
// 初始化
dp[1] = 1;
// 向后推导,累加前面两数之和
for(int i = 2; i <= n; ++i){
dp[i] = dp[i - 1] + dp[i - 2];
}
// 返回结果
return dp[n];
}
}
方式四:动态规格优化
在方式三中,我们定义了一个长度为n
的数组,实际的计算过程中使用到的只有i
之前的两位元素,那么我们可以定义两个变量用来存放前面的结果,省略掉其它的。
class Solution {
public int fib(int n) {
// 边界判断
if(n < 2){
return n;
}
int front = 0, after = 1, tmp;
for(int i = 2; i <= n; ++i){
// 更新状态
tmp = after;
after += front;
front = tmp;
}
return after;
}
}
最后
文章有写的不好的地方,请大佬们不吝赐教,错误是最能让人成长的,愿我与大佬间的距离逐渐缩短!
如果觉得文章对你有帮助,请 点赞、收藏、关注、评论 一键四连支持,你的支持就是我创作最大的动力!!!