标签:cache return 07 22 min coins 322 amount dp
322. 零钱兑换
链接:https://leetcode-cn.com/problems/coin-change/
感想
看了半天题解,才理解。估计过一个月再来做,还是做不出来,我一定是个废物。
解法1:动态规划
(1)第一步:定义数组元素的含义
用一个一维数组来表示当前构成i
的面额,最小需要多少枚硬币
(2)第二步:找出数组元素之间的关系式
dp[i] = min(dp[i], dp[i - conis[j]] + 1)
这个动态规划方程不太好想,当前dp[i]
,枚举的最后一枚硬币的面值是coins[j]
,需要取conis[j-1], coins[j-2], ...coins[0]
的最小值,再加上当前这枚硬币的数量
(3)第三步:找出初始值
当i === 0
时,无法用硬币组成,为0
,当i < 0
时忽略dp[i]
var coinChange = function (coins, amount) {
const len = coins.length,
dp = [0];
for (let i = 1; i <= amount; i++) {
dp[i] = amount + 1;
for (let j = 0; j < len; j++) {
if (coins[j] <= i) {
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
}
}
}
return dp[amount] > amount ? -1 : dp[amount];
};
- 时间复杂度:
${O(S * N)}$
,S
为金额,N
为面额数 - 空间复杂度:
${O(S)}$
- 执行用时:96ms, 在所有JavaScript提交中击败了100%的用户,内存消耗:43.3MB,在所有JavaScript提交中击败了37%的用户
解法2:记忆化搜索
解法1是从下向上的思路,现在从上之下考虑,需要利用递归
判断金额凑不出的小技巧:先初始化DP table各个元素为
amount + 1
(代表不可能存在的情况),在遍历时如果金额凑不出则不更新,于是若最后结果仍然是amount + 1
,则表示金额凑不出
var coinChange = function (coins, amount) {
if (amount < 1) {
return 0;
}
return change(coins, amount);
};
function change(coins, amount, cache = {}) {
// 结束条件1:无法凑成对应的金额
if (amount < 0) {
return -1;
}
// 结束条件2:凑成了想要的结果,直接返回
if (amount === 0) {
return 0;
}
// 以前计算过的值也直接返回
if (cache[amount]) {
return cache[amount];
}
// 填充一个比当前金额更大的值,用 Infinity 也可以
let min = amount + 1;
// 去遍历所有的硬币
for (let i = 0, len = coins.length; i < len; i++) {
// 获得一个结果
const temp = change(coins, amount - coins[i], cache);
// 如果符合条件,并且比当前金额小,才可以更新
if (temp >= 0 && temp < min) {
min = temp + 1;
}
}
cache[amount] = min === amount + 1 ? -1 : min;
return cache[amount];
}
- 时间复杂度:
${O(S * N)}$
,S
为金额,N
为面额数 - 空间复杂度:
${O(S)}$
- 执行用时:140ms, 在所有JavaScript提交中击败了59%的用户,内存消耗:44.5MB,在所有JavaScript提交中击败了14%的用户
标签:cache,return,07,22,min,coins,322,amount,dp 来源: https://blog.csdn.net/duola8789/article/details/118994049
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。