https://leetcode.com/problems/coin-change
以下输入将超时,如果19-> 18或更小,它将通过。
[1,2,5]
19
// e.g. n === [1, 2, 5]
// e.g. t === target sum
// c === counter, count each level
// h === hash, memo
var cc = function(n, t, c, h) {
// index
const index = t;
// if we saw before, return it
if(h[index]) {
return h[index];
}
else if(t === 0) {
// we use all the target, return the counter
return c;
}
// mi === minimum counter
let mi = Infinity;
// e.g. we loop [1, 2, 5]
for(let i=0; i<n.length; i++) {
// only allow positive
if(t-n[i] >= 0) {
// recursive
// mi === Infinity
// t-n[i], consume it
// c+1, increase the counter
// h, pass down the hash
mi = Math.min(mi, cc(n, t-n[i], c+1, h));
}
}
// Update h[index] when mi < h[index]
h[index] = mi < h[index] ? mi : h[index];
return mi;
}
var coinChange = function(n, t) {
const res = cc(n, t, 0, {});
const out = res === Infinity ? -1 : res;
return out;
};
有人知道出了什么问题吗?
答案 0 :(得分:2)
代码至少有一个问题。要查看,请更改此行:
h[index] = mi < h[index] ? mi : h[index];
对此:
console.log(`Before: t: ${ t }, mi: ${ mi }, h[index]: ${ h[index] }`);
h[index] = mi < h[index] ? mi : h[index];
console.log(`After: t: ${ t }, mi: ${ mi }, h[index]: ${ h[index] }`);
并致电:
console.log(coinChange([1,2,5], 3));
我认为,另一个问题是想要更新记录在h[index]
中的结果与希望返回存储在其中的结果之间的差异,然后才能进行更新。
假设我们可以通过各种方式达到目标0,那么请考虑一下,如果第一个递归分支通过许多步骤到达那里,当前会发生什么。
答案 1 :(得分:2)
以下内容可以通过测试用例。
修复了何时更新哈希值
// keep it infinity or 0 or positive
h[index] = (h[index] === undefined ? mi : mi < h[index] ? mi : h[index]);
计数器仅在功能内部发生。没有混淆
result = cc(n, t-n[i], h)
var cc = function(n, t, h) {
// index
const index = t;
// reach 0, re 0
if(t === 0) {
return 0;
} else if(h[index] !== undefined) {
// hash
return h[index];
}
// min
let mi = Infinity;
// loop coin
for(let i=0; i<n.length; i++) {
// posi, get in
if(t-n[i] >= 0) {
// return count or hash
mi = Math.min(mi, cc(n, t-n[i], h)+1);
}
}
// keep it infinity or 0 or positive
h[index] = (h[index] === undefined ? mi : mi < h[index] ? mi : h[index]);
return h[index];
}
var coinChange = function(n, t) {
const res = cc(n, t, {});
const out = res === Infinity ? -1 : res;
return out;
};
答案 2 :(得分:0)
如果我们使用额外的内存来解决问题,也许会更容易:
const coinChange = function(coins, amount) {
const inf = Math.pow(2, 31)
const dp = []
dp[0] = 0
while (dp.length <= amount) {
let curr = inf - 1
for (let index = 0; index < coins.length; index++) {
if (dp.length - coins[index] < 0) {
continue
}
curr = Math.min(curr, 1 + dp[dp.length - coins[index]])
}
dp.push(curr)
}
return dp[amount] == inf - 1 ? -1 : dp[amount]
};
Python:
class Solution:
def coinChange(self, coins, target):
dp = [0] + [float('inf')] * target
for index in range(1, target + 1):
for coin in coins:
if index - coin >= 0:
dp[index] = min(dp[index], dp[index - coin] + 1)
return -1 if dp[-1] == float('inf') else dp[-1]
使用辅助函数(Java):
class Solution {
public int coinChange(int[] coins, int target) {
if (target < 1)
return 0;
return helper(coins, target, new int[target]);
}
private int helper(int[] coins, int rem, int[] count) {
if (rem < 0)
return -1;
if (rem == 0)
return 0;
if (count[rem - 1] != 0)
return count[rem - 1];
int min = Integer.MAX_VALUE;
for (int coin : coins) {
int res = helper(coins, rem - coin, count);
if (res >= 0 && res < min)
min = 1 + res;
}
count[rem - 1] = (min == Integer.MAX_VALUE) ? -1 : min;
return count[rem - 1];
}
}