文章目录
- [81 爬楼梯](#81 爬楼梯)
- [82 杨辉三角](#82 杨辉三角)
- [83 打家劫舍](#83 打家劫舍)
- [84 完全平方数](#84 完全平方数)
- [85 零钱兑换](#85 零钱兑换)
81 爬楼梯
- 动态规划
- 爬1个台阶1种方法(一次一阶),爬2个台阶两种方法(两次一阶、一次两阶),爬3阶台阶3种方法(在第一阶的基础上再迈一步,一步两阶;在第二阶的基础上再迈一步,一步一阶)...
- dp[i]:到达第i阶有dp[i]种方法。
- dp[i] = dp[i - 1] + dp[i - 2]
- 初始化:dp[0]无意义,dp[1] = 1,dp[2] = 2。
javascript
/**
* @param {number} n
* @return {number}
*/
var climbStairs = function(n) {
let dp = Array(n + 1).fill(0);
dp[1] = 1, dp[2] = 2;
for(let i = 3; i <= n; i++){
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
};
82 杨辉三角
- 动态规划
- 可转化为这种形式:
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1] - dp[i][j]:第i行第j列的数字。
- 由题意可得,第0列和行号 = 列号时,dp[i][j] = 1,因此dp初始化为1。
- 其他位置:dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]。
javascript
/**
* @param {number} numRows
* @return {number[][]}
*/
var generate = function(numRows) {
let dp = Array(numRows).fill(null).map(() => Array(numRows).fill(1));
let res = [[1]];
for(let i = 1; i < numRows; i++){
let tmp = [1];
for(let j = 1; j < i; j++){
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
tmp.push(dp[i][j]);
}
tmp.push(1);
res.push(tmp);
}
return res;
};
83 打家劫舍
- 动态规划
- dp[i]:偷下标为[0, i]房屋的最大金币数。
- 偷i:dp[i - 2] + nums[i],不偷i:dp[i - 1]。
- dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])
- 初始化:dp[0] = nums[0],dp[1] = max(nums[0], nums[1]),其他位置初始化为0。
javascript
/**
* @param {number[]} nums
* @return {number}
*/
var rob = function(nums) {
let dp = Array(nums).fill(0);
dp[0] = nums[0], dp[1] = Math.max(nums[0], nums[1]);
for(let i = 2; i < nums.length; i++){
dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
}
return dp[nums.length - 1];
};
84 完全平方数
- 动态规划
- dp[j]:拼成j所需完全平方数的最少数量。
- 两层for循环,这里先遍历完全平方数,再遍历整数(先遍历整数,后遍历完全平方数也可,遍历顺序变化不影响结果)。
- dp[j] = min(dp[j], dp[j - i * i] + 1)
- 初始化:dp[0] = 0,最后求最小值,因此其他初始化为极大值。
javascript
/**
* @param {number} n
* @return {number}
*/
var numSquares = function(n) {
let dp = Array(n + 1).fill(Number.MAX_SAFE_INTEGER);
dp[0] = 0;
for(let i = 1; i * i <= n; i++){
for(let j = i * i; j <= n; j++){
dp[j] = Math.min(dp[j], dp[j - i * i] + 1);
}
}
return dp[n];
};
85 零钱兑换
- 动态规划
- dp[j]:凑成i所需要的最少硬币数量。
- 两层for循环,这里先遍历完全平方数,再遍历整数(先遍历整数,后遍历完全平方数也可,遍历顺序变化不影响结果)。
- dp[j] = min(dp[j], dp[j - coins[i]] + 1)
- 相当于分别引入1,2...,开始时只有硬币1,所需要的硬币数就分别为1,2,3,4...,后面引入2就可以变成1, 1, 2, 2...。
- 初始化:dp[0] = 0,最后求最小值,因此其他初始化为极大值。
javascript
/**
* @param {number[]} coins
* @param {number} amount
* @return {number}
*/
var coinChange = function(coins, amount) {
let dp = Array(amount + 1).fill(Number.MAX_SAFE_INTEGER);
dp[0] = 0;
for(let i = 0; i <= coins.length; i++){
for(let j = coins[i]; j <= amount; j++){
dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);
}
}
return dp[amount] == Number.MAX_SAFE_INTEGER? -1: dp[amount];
};