322. 零钱兑换
题目链接: 322. 零钱兑换 - 力扣(LeetCode)
文章讲解: 代码随想录
思路:
确定递推公式:
dp[j]=min(dp[j],dp[j-coins[i]]+1);
由于是完全背包 ,所以遍历顺序是正序
还存在另一个问题 没有任何一种硬币组合能组成总金额
其实也就是没更新 dp
cpp
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<double>dp2(amount+1,0);
dp2[0]=0;
for(int i=0;i<coins.size();i++){
for(int j=coins[i];j<=amount;j++){
dp2[j]=max(dp2[j],dp2[j-coins[i]]+coins[i]);
}
}
if(dp2[amount]!=amount)
return -1;
vector<int>dp(amount+1,INT_MAX-2);
dp[0]=0;
for(int i=0;i<coins.size();i++){
for(int j=coins[i];j<=amount;j++){
dp[j]=min(dp[j],dp[j-coins[i]]+1);
}
}
return dp[amount];
}
};
需要注意的是:完全背包的两层for循环强调先后顺序
但是排列 或组合问题是强调先后顺序的
279.完全平方数
题目链接:279. 完全平方数 - 力扣(LeetCode)
文章讲解:代码随想录
思路:
这道题跟上题几乎一样
cpp
class Solution {
public:
int numSquares(int n) {
vector<int>nums;
for(int i=1;i<=sqrt(n);i++){
nums.push_back(i*i);
}
vector<int>dp(n+1,INT_MAX);
dp[0]=0;
for(int i=0;i<nums.size();i++){
for(int j=nums[i];j<=n;j++){
dp[j]=min(dp[j],dp[j-nums[i]]+1);
}
}
return dp[n];
}
};
139.单词拆分
文章讲解:代码随想录
思路:
这道题可以理解为一个完全背包问题
那么需要考虑 背包容量 物品
物品就是单词
背包容量呢 就是字符串s的长度
完全背包 那么是排列问题还是组合问题 这是排列问题 所以先遍历背包
dp[i]表示前i个字符能被分割
字符串有函数s.substr(i,n)表示从位置i开始分割长度为n的字符串
注意递推公式:
cpp
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
unordered_set<string>myset(wordDict.begin(),wordDict.end());
vector<bool>dp(s.size()+1,false);
dp[0]=true;
for(int i=1;i<dp.size();i++){
for(int j=0;j<i;j++){
string word=s.substr(j,i-j);
if(myset.find(word)!=myset.end()&&dp[j]==true) {dp[i]=true;}
}
}
return dp[s.size()];
}
};