题解1:(动态规划解法)
动态规划问题可划分为五部曲:
- 确定dp数组以及下标的含义:这里的的dp[i]是指第i个数的斐波那契数列的值dp[i] ;
- 确定递推公式:由于斐波那契数列的值是由该位置前两项的值决定的,因此可以得到递推公式 dp[i] = dp[i-1] + dp[i-2] ;
- 确定dp数组初始化的值,这里我们知道斐波那契数列的前两项为 0 和 1,那么dp[0] = 0 ,dp[1] = 1 ;有了初始化的值,就可以向后不断递推;
- 确定遍历顺序,我们可以从题意中知道,斐波那契数列的值是由前两项的值得到的,那么自然而然就得从前面开始遍历,才能通过前面的值得到后续位置上的值;
- 举例推导递推公式,我们可以写出斐波那契数列的正确结果,然后自己尝试通过递推公式,能否得到正确的值;
具体代码如下:
var fib = function(n) {
const dp = []
dp[0] = 0 , dp[1] = 1
for(let i = 2 ; i <= n ; i++) {
dp[i] = dp[i-1] + dp[i-2]
}
return dp[n]
};
时间复杂度:O(n) 空间复杂度:O(n)
题解2:动态规划解法优化
我们发现上述代码,其实可以只维护两个数值就可以了,不需要记录整个斐波那契序列,因此可以对代码进行优化,降低空间复杂度。
需要注意的是:下面代码中最终结果返回dp[1],这里我们将这个dp[1]理解为是for循环结束最终得到的结果,将dp[1]看作是一个变量,而不是一个表示斐波那契数列1位置上的值。
var fib = function(n) {
if(n <= 1) return n
const dp = []
dp[0] = 0
dp[1] = 1
for(let i = 2 ; i <= n ; i++) {
let sum = dp[0] + dp[1]
dp[0] = dp[1]
dp[1] = sum
}
return dp[1]
};
时间复杂度:O(n) 空间复杂度:O(1)
题解3:递归解法
递归解法的代码书写更简洁,但时间复杂度比上述两种方法高。
var fib = function(n) {
//此处写成 n<=1 和 n<2皆可
if(n <= 1) return n
return fib(n-1) + fib(n-2)
};
时间复杂度:O(2^n) 空间复杂度:O(n)