2022-11-04 13:43阅读: 13评论: 0推荐: 0

力扣-322-零钱兑换

一眼和昨天做的,一个梳子最少能用几个完全平方数凑成不是神似?
不过这里不一样的是,这里真的是背包问题,完全背包

瞄一眼确实是凑完全平方数那种方法,其实不太理解哪里能算是背包了

有个麻烦点是怎么返回-1的情况

自己都不确定对居然能通过了

int coinChange(vector<int>& coins, int amount) {
vector<int> dp(amount + 1,amount+1);
dp[0] = 0;
sort(coins.begin(), coins.end());
for (int i = 1; i <= amount; i++) {
for (int j = 0; j < coins.size(); j++) {
if (i == coins[j]) dp[i] = 1;
else if(i>coins[j]) dp[i] = min(dp[i],dp[i - coins[j]] + 1);
}
}
return dp[amount]>amount?-1:dp[amount];
}

来分析一下这代码为什么对,以及做一个空间优化

  1. 首先,虽然递推过程更像是一个递归过程,但是我们要用动态规划自底向上避免重复计算造成的超时问题
    也就是第一层循环
  2. 其次,对于等于数组中元素的数直接dp[i]=1,这个没什么说的,下面递归过程取最小的过程其实也没什么说的
  3. 关键是凑不成的情况怎么处理?
    举例:拿5,13去凑3,7
  • 对于小于coins中最小的元素,肯定凑不成的,这也是为什么我要对coins排一遍,还想着直接return -1这肯定是不对的,那怎么让跟其他结果比较的时候知道这条路径不可取呢?
    我们取的是最小值,那我们就把它置大,让它绝对不会作为合理的结果被选中
    值多大呢?在哪里置?
    初始化置,置一个绝对不会是正确答案的最小值,amount+1,就算全拿1来凑也最大amount,当然还有一种意外情况,就是amount=0,所以这里单独初始化
  • 对于f(3)=f(1)+1,会被转化,所以还是只要考虑小于最小的coin的元素就行
    这里的sort是多余的吗?找出最小的coin大小,不完全多余,是可以先处理比最小coin小的元素
    但是没必要,因为首先这多了一步sort,带来额外的时间复杂度,另外不单独处理其实也行,用前面说的初始化置amount+1

然后考虑空间优化的问题…感觉不好空间优化啊,这又不是线性的
好,看一眼刷题笔记,确实这个dp数组是不能优化的,但是有一句语句是不不必要的
if (i == coins[j]) dp[i] = 1;
这里的情况能被下面的语句包含,如果i==coin[j]的话,dp[i-coin[j]]==dp[0]=0+1=1
然后这里的也是不必要的,没有单独使用到j的情况,用增强for的话能省一个变量同时迭代器效率更高

最简洁的样子就是这样:

int coinChange(vector<int>& coins, int amount) {
vector<int> dp(amount + 1, amount + 1);
dp[0] = 0;
for (int i = 1; i <= amount; i++)
for (int coin : coins)
if (i >= coin) dp[i] = min(dp[i], dp[i - coin] + 1);
return dp[amount] > amount ? -1 : dp[amount];
}

本文作者:YaosGHC

本文链接:https://www.cnblogs.com/yaocy/p/16857488.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   YaosGHC  阅读(13)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起