力扣-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]; }
来分析一下这代码为什么对,以及做一个空间优化
- 首先,虽然递推过程更像是一个递归过程,但是我们要用动态规划自底向上避免重复计算造成的超时问题
也就是第一层循环 - 其次,对于等于数组中元素的数直接dp[i]=1,这个没什么说的,下面递归过程取最小的过程其实也没什么说的
- 关键是凑不成的情况怎么处理?
举例:拿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 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步