代码随想录算法训练营第44天 [ 322. 零钱兑换 279.完全平方数 139.单词拆分]
如果求组合数就是外层for循环遍历物品,内层for遍历背包。
如果求排列数就是外层for遍历背包,内层for循环遍历物品。
一、322. 零钱兑换
链接: 代码随想录.
思路:
dp[i] 下标为i的 背包 所需硬币的最小值为 dp[i]
因为是最小值,所以初始化为最大值 dp[0] = 0
递推公式 dp[j] = min(dp[j] ,dp[j-coins[i]] + 1)
无限使用-> 完全背包做题状态:看解析后做出来了
cpp
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
// dp[i] 下标为i的 背包 所需硬币的最小值为 dp[i]
// 因为是最小值,所以初始化为最大值 dp[0] = 0
// 递推公式 dp[j] = min(dp[j] ,dp[j-coins[i]] + 1)
// 无限使用-> 完全背包
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] = min(dp[j], dp[j - coins[i]] + 1);
}
}
if (dp[amount] == INT_MAX) {
return -1;
}
return dp[amount];
}
};
二、279.完全平方数
链接: 代码随想录.
思路: 完全背包 背包大小为n 物品为[1,4,9,16...]
dp[n] 表示 n的完全平方数的最少数量为dp[n] 因为是最少数量
初始化为INT_MAX
dp[0] = 0
递推公式 dp[j] = dp[j-i * i]+1;做题状态:看解析后做出来了
cpp
class Solution {
public:
int numSquares(int n) {
// 完全背包 背包大小为n 物品为[1,4,9,16...]
// dp[n] 表示 n的完全平方数的最少数量为dp[n] 因为是最少数量
// 初始化为INT_MAX
// dp[0] = 0
// 递推公式 dp[j] = dp[j-i*i]+1;
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], dp[j - i * i] + 1);
}
}
return dp[n];
}
};
三、139.单词拆分
链接: 代码随想录.
思路:注释
做题状态:看解析后做出来了
cpp
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
// dp[i] 表示下标为i的字符串,可不可以被用单词拼接
// 单词出现的顺序很重要 顺序不对不能组成单词 ,所以是排列问题
// 先遍历背包,再遍历物品
// 递推公式 单词在wordDict中存在 && dp[j](起点) == true
unordered_set<string> wordSet(wordDict.begin(), wordDict.end());
vector<bool> dp(s.size() + 1, false);
dp[0] = true;
for (int i = 1; i <= s.size(); i++) { //i是从s的第一位一直到最后一位
for (int j = 0; j < i; j++) { //j是从下标0开始,一直到选取的终点i
string word = s.substr(j, i - j); //获取到了i的每个字串 比如i选的是leet 就能获得 leet eet et t
cout << word <<" ";
if(wordSet.find(word) != wordSet.end() && dp[j]){
dp[i] = true;
}
}
}
return dp[s.size()];
}
};