本文主要是介绍代码随想录第四十五天——爬楼梯,零钱兑换,完全平方数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
leetcode 70. 爬楼梯
题目链接:爬楼梯
爬楼梯也可以通过完全背包的解法求解。
- 确定dp数组以及下标的含义
dp[i]
:爬到有i个台阶的楼顶,有dp[i]种方法 - 确定递推公式
求装满背包的方法数的递推公式都是dp[i] += dp[i - nums[j]]
所以本题的递推公式:dp[i] += dp[i - j]
- dp数组初始化
dp[0]=1;其他初始化为0 - 确定遍历顺序
本题是背包里的求排列问题,即:1、2 步 和 2、1 步都是上三个台阶,但是这两种方法不一样。
所以需将target放在外循环,将nums放在内循环并从前向后遍历
class Solution {
public:int climbStairs(int n) {vector<int> dp(n + 1,0);dp[0] = 1;for(int i = 1;i <= n;i++) {for(int j = 1;j <= 2;j++) {if(i - j >= 0) dp[i] += dp[i - j];}}return dp[n];}
};
leetcode 322. 零钱兑换
题目链接:零钱兑换
- 确定dp数组以及下标的含义
dp[j]
:凑足总额为 j 所需钱币的最少个数为dp[j] - 确定递推公式
凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j](考虑coins[i]),所以dp[j] 要取所有 dp[j - coins[i]] + 1 中最小的。
递推公式:dp[j] = min(dp[j - coins[i]] + 1, dp[j])
- dp数组初始化
dp[0] = 0;
dp[j]必须初始化为最大的数,否则就会在min(dp[j - coins[i]] + 1, dp[j])比较的过程中被初始值覆盖,所以下标非0的元素应该初始化为最大值。
vector<int> dp(amount + 1, INT_MAX);dp[0] = 0;
- 确定遍历顺序
本题不强调元素的顺序。所以对于物品和背包的内外层遍历都可以。完全背包问题,内循环正序。
版本一:外层遍历物品,内层遍历背包
class Solution {
public:int coinChange(vector<int>& coins, int amount) {vector<int> dp(amount + 1, INT_MAX);dp[0] = 0;for (int i = 0; i < coins.size(); i++) { // 遍历物品for (int j = coins[i]; j <= amount; j++) { // 遍历背包if (dp[j - coins[i]] != INT_MAX) { // 如果dp[j - coins[i]]是初始值则跳过dp[j] = min(dp[j - coins[i]] + 1, dp[j]);}}}if (dp[amount] == INT_MAX) return -1;return dp[amount];}
};
时间复杂度: O(n * amount),其中 n 为 coins 的长度
空间复杂度: O(amount)
版本二:外层遍历背包,内层遍历物品
class Solution {
public:int coinChange(vector<int>& coins, int amount) {vector<int> dp(amount + 1, INT_MAX);dp[0] = 0;for (int i = 1; i <= amount; i++) { // 遍历背包for (int j = 0; j < coins.size(); j++) { // 遍历物品if (i - coins[j] >= 0 && dp[i - coins[j]] != INT_MAX ) {dp[i] = min(dp[i - coins[j]] + 1, dp[i]);}}}if (dp[amount] == INT_MAX) return -1;return dp[amount];}
};
leetcode 279. 完全平方数
题目链接:完全平方数
本题可以解释为:完全平方数就是物品(可以无限件使用),凑个正整数n就是背包,问凑满这个背包最少有多少物品?
版本一:外层遍历物品,内层遍历背包
class Solution {
public:int numSquares(int n) {vector<int> dp(n + 1, INT_MAX);dp[0] = 0;for (int i = 1; i * i <= n; i++) { // 遍历物品for (int j = i * i; j <= n; j++) { // 遍历背包dp[j] = min(dp[j - i * i] + 1, dp[j]);}}return dp[n];}
};
版本二:外层遍历背包,内层遍历物品
class Solution {
public:int numSquares(int n) {vector<int> dp(n + 1, INT_MAX);dp[0] = 0;for (int i = 0; i <= n; i++) { // 遍历背包for (int j = 1; j * j <= i; j++) { // 遍历物品dp[i] = min(dp[i - j * j] + 1, dp[i]);}}return dp[n];}
};
这篇关于代码随想录第四十五天——爬楼梯,零钱兑换,完全平方数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!