零钱兑换
学习记录自代码随想录
要点:1.背包容量为amount,物品重量为coins[i],物品价值为1;
2.因为求最小值递推公式为 d p [ j ] = m i n ( d p [ j ] , d p [ j − c o i n s [ i ] ] + 1 ) dp[j] = min(dp[j], dp[j-coins[i]]+1) dp[j]=min(dp[j],dp[j−coins[i]]+1);
3.dp数组初始化,因为是min所以dp[0] = 0, 其余值初始化为UINT_MAX;
4.在迭代判断时要跳过dp[j-coins[i]] == INT_MAX这种情况,并且此时也没有比较的必要,但是不能不加这个条件,因为UINT_MAX+1会回滚到0导致迭代出错;
c
unsigned int min(unsigned int a, unsigned int b){
return a < b ? a : b;
}
int coinChange(int* coins, int coinsSize, int amount) {
if(amount == 0) return 0;
// int sum = 0;
// for(int i = 0; i < coinsSize; i++) sum += coins[i];
// 1.dp[j]代表凑成总金额为j(背包容量)时所需的最少的硬币个数, 物品重量为coins[i], 物品价值为1
unsigned int dp[amount+1];
memset(dp, UINT_MAX, sizeof(dp));
// memset(dp, 0, sizeof(dp));
// 2.递推公式:dp[j] = max(dp[j], dp[j-coins[i]] + 1)
// 3.dp数组初始化为UINT_MAX
dp[0] = 0;
// 4.遍历顺序,每个物品可以无限拿,所以先物品再背包, 均为正向遍历
for(int i = 0; i < coinsSize; i++){
for(int j = coins[i]; j < amount+1; j++){
// 如果dp[j-coins[i]]为UINT_MAX,则UINT_MAX+1会重新变为0导致整体迭代会出错需要注意!
if(dp[j-coins[i]] != UINT_MAX){
dp[j] = min(dp[j], dp[j-coins[i]] + 1);
}
}
}
// 5.举例推导dp数组
if(dp[amount]) return dp[amount];
return -1;
}