70.爬楼梯、322.零钱兑换、279.完全平方数
70.爬楼梯
这是当初做过的一道题,当初是直接用动态规划做的,此时也可以用完全背包来做。
我们将其假设为完全背包。
dp数组的含义为:到达某一楼梯的方法数(视为某一个容量的方法)
dp的动态更新思路为:可以向背包装入大小为1或者2的物品。
因此,背包的更新算法为for(int j =1;j<=2;j++) { dp[ii]+=dp[ii-j]; }
dp数组的初始化:因为到达0和1个方法只有一种,因此,我们令其为1。
从前向后遍历。
class Solution {
public:
int climbStairs(int n) {
if(n<=1) return 1;
vector<int>dp(n+1,0);
dp[0] = 1;
dp[1] = 1;
for(int ii = 2;ii<=n;ii++)
{
for(int j =1;j<=2;j++)
{
dp[ii]+=dp[ii-j];
}
}
return dp[n];
}
};
322.零钱兑换
这道题是要求符合要求的最小硬币数,我们用完全背包进行求解。
首先对背包进行定义。dp[ii]表示,容量为ii的背包最少硬币数。
推导公式:我们遍历某个背包的容量ii时,如果此时有某个容量ii-coins[jj]可以满足,加入一个硬币coins[jj]使得硬币数更少,那么我们更新这个容量的大小,使其为这个更小值。
初始化:我们假设初试dp[0]为零,即没有容量没有硬币,其他容量的数值为INT_MAX,这样方便我们进行求最小值。
我们从小到大进行遍历。
代码
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int>dp(amount+1,INT_MAX);
dp[0] = 0;
for(int ii =1;ii<amount+1;ii++)
{
for(int jj =0;jj<coins.size();jj++)
{
if(ii>=coins[jj]&&dp[ii-coins[jj]]!=INT_MAX)
dp[ii] = min(dp[ii],dp[ii-coins[jj]]+1);
}
}
if(dp[amount]==INT_MAX) return -1;
return dp[amount];
}
};
279.完全平方数
对于该题,我们的思路为确定一个dp数组,用来记录0-n数字所能记录的最少完全平方数,在遍历的过程中,对于数字n,我们从1到根号n(取整)进行遍历,如果存在某种组合的完全平方数的数量使得dp[n]更小,我们就更新dp[n]。
回溯四部曲:
1.dp数组的含义,dp[n]表示对于数字n包含的最少完全平方数。
2.dp数组的推导公式,我们取dp[n]= min(dp[n],dp[n-jjjj]+1),即取当前的dp[n]数量和dp[n-jjjj]的数量+1 的最小值。
3.初试化,我们对dp[0]=0,dp[1]=1,其他数字为INT_MAX,方便我们进行求最小值。
4.从小到大进行遍历。
代码
class Solution {
public:
int numSquares(int n) {
vector<int>dp(n+1,INT_MAX);
dp[0] = 0;
dp[1] = 1;
for(int ii =2;ii<n+1;ii++)
for(int jj =1;jj<=sqrt(ii);jj++)
dp[ii] = min(dp[ii],dp[ii-jj*jj]+1);
return dp[n];
}
};