- leetcode 70.爬楼梯-排列问题+求种类问题
class Solution {
public:
int climbStairs(int n) {
vector<int> dp(n+1,0);//爬到第j层楼梯有dp[j]种方法
dp[0]=1;
for(int j=0;j<=n;j++){//排列问题,先遍历背包
for(int i=1;i<=2;i++){
if(j>=i)
dp[j]+=dp[j-i];//背包问题中求种类数常用的递归公式
}
}
return dp[n];
}
};
- leetcode 322. 零钱兑换
本题dp数组的含义是硬币个数,不强调组合或者排列,不同种的排列但是同一种组合的硬币集合对应的硬币个数是一样的
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int> dp(amount+1,INT_MAX);//凑成金额为j最小需要硬币个数为dp[j]个
dp[0]=0;
for(int i=0;i<coins.size();i++){//遍历物品 本题dp数组是硬币个数,不强调排列或者是组合,因此先遍历谁都可以
for(int j=coins[i];j<=amount;j++){//遍历背包,背包在内循环的时候,j的初始值为coins[i],如果背包在外的话背包只能从0开始遍历了
if(dp[j - coins[i]] != INT_MAX )//防止int越界,这里挺坑的
dp[j]=min(dp[j],dp[j-coins[i]]+1);
}
}
if(dp[amount]==INT_MAX) return -1;
return dp[amount];
}
};
- leetcode 279. 完全平方数
这题和零钱兑换那题一样,只是我不知道为啥不需要判断dp[j-i*i]!=INT_MAX,不知道以后能不能悟
class Solution {
public:
int numSquares(int n) {
vector<int> dp(n+1,INT_MAX);//组成j的完全平方数的最少数量为dp[j]
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);//不知道为啥这里不需要判断dp[j-i*i]!=INT_MAX,不知道以后能不能悟
}
}
return dp[n];
}
};
leetcode 139.单词拆分
本题强调物品的顺序,因此先遍背包,再遍历物品
本题dp数组也要定义为s.size()+1,dp[0]用来递推后面的状态。
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
unordered_set wordSet(wordDict.begin(),wordDict.end());
vector<bool> dp(s.size()+1,false);
dp[0]=true;//dp[0]其实没啥意义,主要是为递推公式服务的
for(int j=1;j<=s.size();j++){//这里从1开始,因为题目说了s.size()>=1,
for(int i=0;i<=j;i++){
string word=s.substr(i,j-i);//递推逻辑
if(wordSet.find(word)!=wordSet.end()&&dp[i]==true){
dp[j]=true;
}
}
}
return dp[s.size()];
}
};