题目:
1.斐波那契数
2.爬楼梯
3.斐波那契数列
和第四题一模一样
代码:
//1.斐波那契数
var fib = function(n) {
//动规思路:1.dp数组;2.初始化;3.递推公式;4.遍历顺序;
//要明白dp数组含义 dp[i] 表示第i个斐波那契数
let dp =[];
//初始化dp数组
dp[0] =0;
dp[1] = 1;
//边界判断
if(n < 2) return n;
//遍历顺序:从前到后; 递推公式:dp[i] = dp[i-1] + dp[i-2];
for(let i = 2; i <= n;i++){
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
};
//2.爬楼梯
//2.1 空间复杂度 O(n)
var climbStairs = function(n) {
//dp[i] 表示爬到第i个台阶有几种办法
//递推公式:dp[i] = dp[i-1] + dp[i-2] i>2 i从1开始
//dp数组初始化: dp[0] = 0, dp[1] = 1, dp[2] = 2
let dp = [];
dp[0] = 0, dp[1] = 1, dp[2] = 2;
if(n < 3) return n;
for(let i = 3; i <= n; i++){
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
};
//2.2 空间复杂度 O(1) 利用滚动数组法
var climbStairs = function(n) {
//dp[i] 表示爬到第i个台阶有几种办法
//采用滚动数组的思想
let pre = 1, cur = 1;
if(n === 1) return 1;
for(let i = 2; i <= n; i++){
const temp = cur; //temp的作用:为pre提供i-1台阶的方法数
cur = cur + pre; //台阶i的方法数
pre = temp; //保存前一个台阶的方法数
}
return cur;
};
//3.斐波那契数列
//3.1 一般方法
var fib = function(n) {
//动规思路:1.dp数组;2.初始化;3.递推公式;4.遍历顺序;
//要明白dp数组含义 dp[i] 表示第i个斐波那契数
let dp =[];
//初始化dp数组
dp[0] =0;
dp[1] = 1;
//边界判断
if(n < 2) return n;
//遍历顺序:从前到后; 递推公式:dp[i] = dp[i-1] + dp[i-2];
for(let i = 2; i <= n;i++){
dp[i] = (dp[i-1] + dp[i-2])% 1000000007 ; //这是和斐波那契数唯一不同的地方
}
return dp[n];
};
//3.2 利用滚动数组的思想
var fib = function(n) {
let pre = 0, cur = 1;
if(n < 2) return n;
for(let i = 2; i <= n;i++){
const tem = cur;
cur = (cur+pre) % 1000000007;
pre = tem;
}
return cur;
};
//4.连续子数组的最大和
var maxSubArray = function(nums) {
/*
1.dp[i] 表示以nums[i]为结尾的连续子数组的最大和
2.状态转移方程:
如果dp[i-1] > 0, dp[i] = dp[i-1]+nums[i]
如果dp[i-1] <= 0,dp[i] = nums[i]
3.初始化:dp[0] = nums[0]
4.输出:max(dp)
*/
const length = nums.length;
if(length == 0) return 0;
let dp = new Array();
dp[0] = nums[0];
let res = dp[0];//res来保存dp[i-1]
for(let i = 1; i < length; i++){
dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
res = Math.max(res,dp[i]); //更新res,让res始终为dp数组中的最大值 ,滚动数组思想
}
return res;
};