我想解决零钱的问题.我使用了两段类似的代码,但结果是一段通过,而另一段运行超时.我想知道为什么这两段类似的代码有两个不同的结果,请解释一下原理.

这个问题的leetcode链接: https://leetcode.cn/problems/coin-change/description/

超过时限的输入是:

币= [186 419,83,408]

金额= 6249

1.通过一:

var coinChange = function(coins, amount) {
    const filter = amount + 1;
    const memo = new Array(amount + 1).fill(filter);
    const dp = function(coins, amount) {
        if (amount === 0) {
            return 0;
        }
        if (amount < 0) {
            return -1;
        }
        if (memo[amount] !== filter) {
            return memo[amount];
        }
        let res = Infinity;
        for (let coin of coins) {
            let subAmount = dp(coins, amount - coin);
            if (subAmount === -1) {
                continue;
            }
            res = Math.min(res, subAmount + 1);
        }
        memo[amount] = (res === Infinity) ? -1 : res;
        return memo[amount];
    }
    return dp(coins, amount);
}

  1. 一次运行超时:
var coinChange = function(coins, amount) {
    const filter = amount + 1;
    const memo = new Array(amount + 1).fill(filter);
    const dp = function(amount) {
        if (amount === 0) {
            return 0;
        }
        if (amount < 0) {
            return -1;
        }
        if (memo[amount] !== filter) {
            return memo[amount];
        }
        for (let coin of coins) {
            let subAmount = dp(amount - coin);
            if (subAmount === -1) {
                continue;
            }
            memo[amount] = Math.min(memo[amount], subAmount + 1);
        }
        return memo[amount] === filter ? -1 : memo[amount]  
    }
    return dp(amount);
}

推荐答案

最主要的问题是,你并不总是做回忆.代码的两个版本都有一个特殊的值filter,以表示尚未记住任何值.但是当对于一定数量没有解决方案时,错误代码将不会更新memo[amount].是的,它会的,但它的价值是相同的:filter.这意味着你没有记住failure.在这种情况下,正确的代码将存储-1.

所以第一个版本的修复是改变这一点:

    return memo[amount] === filter ? -1 : memo[amount]  

对此:

    if (memo[amount] === filter) memo[amount] = -1;
    return memo[amount];

有了这个修复它将工作.

备注:这不是一个好的做法,有这样的声明:

memo[amount] = Math.min(memo[amount], subAmount + 1);

...因为这还不能保证是正确的、优化的结果.正确的结果只有当你完成了try 所有可能的硬币的循环时才知道.只有这样,您才应该将最终值存储在备忘录表中.幸运的是,它没有负面影响,因为在更深的递归树中判断的所有数量都比这个数量多smaller,所以当这个循环还在运行时,不会参考memo[amount].但是,在记忆化表中只存储最终(优化)值似乎是一个很好的实践.

Javascript相关问答推荐

布局样式在刷新时不持续

是什么原因导致此Angular 16电影应用程序中因类型错误而不存在属性?

Vue:ref不会创建react 性属性

按钮未放置在html dis位置

我开始使用/url?q=使用Cheerio

TypeScript索引签名模板限制

如何通过使用vanilla JS限制字体大小增加或减少两次来改变字体大小

使用Promise.All并发解决时,每个promise 的线性时间增加?

Chart.js-显示值应该在其中的引用区域

如何在FastAPI中为通过file:/URL加载的本地HTML文件启用CORS?

无法避免UV:flat的插值:非法使用保留字"

无法设置RazorPay订阅API项目价格

使用线性插值法旋转直线以查看鼠标会导致 skip

如何组合Multer上传?

FindByIdAndUpdate在嵌套对象中创建_id

如何在Java脚本中并行运行for或任意循环的每次迭代

$GTE的mongoose 问题

ReactJS在类组件中更新上下文

如何在Java脚本中添加一个可以在另一个面板中垂直调整大小的面板?

Playwright:ReferenceError:browserContext未定义