当前位置: 首页 > 知识库问答 >
问题:

硬币兑换问题自上而下方法的比较

钮博裕
2023-03-14

我正在研究Leetcode322:硬币兑换。

您将获得一个整数数组,表示不同面额的硬币,以及一个整数金额,表示总金额。

返回您需要的最少数量的硬币,以弥补该金额。如果这些硬币的任何组合都无法弥补这一数额,则返回-1。

你可以假设每种硬币的数量是无限的。

例子:

输入:硬币=[1,2,5],金额=11

输出: 3

说明:11 = 5 5 1

我选择自上而下的方法,在每次迭代中,我选择一个面额不大于剩余金额的硬币。听起来很容易,对吧?

以下代码通过所有测试用例。

import sys
import functools

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        @functools.cache   
        def _loop(remaining: int) -> int:
            if remaining == 0:
                return 0
            y = sys.maxsize
            for coin in filter(lambda x: x <= remaining, coins):
                y = min(y, _loop(remaining - coin))

            return (y + 1) if y < sys.maxsize else y
        
        num_coins = _loop(amount)
        return num_coins if num_coins < sys.maxsize else -1 

但这一个没有。

import sys
class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        num_coins = self._loop(coins, amount, 0, {})
        return num_coins if num_coins < sys.maxsize else -1
    
    def _loop(self, coins: Sequence[int], remaining: int, count: int, memo: MutableMapping[int, int]) -> int:
        if remaining == 0:
            return count
        if remaining not in memo:
            y = sys.maxsize
            for coin in filter(lambda x: x <= remaining, coins):
                y = min(y, self._loop(coins, remaining - coin, count + 1, memo))
            memo[remaining] = y

        return memo[remaining]

这两种解决方案的唯一区别是,在前者中,1被添加到for循环之后的结果中(因为使用了一枚硬币),在后者中,1被添加到递归调用的参数。

第二个解决方案中我没有看到的错误是什么?

共有2个答案

越星晖
2023-03-14

这里的操作:为了记录在案,这是修复泰哈斯·纳拉扬指出的错误后的工作代码。

import sys
class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        num_coins = self._loop(coins, amount, 0, {})
        return num_coins if num_coins < sys.maxsize else -1
    
    def _loop(self, coins: Sequence[int], remaining: int, count: int, memo: MutableMapping[int, int]) -> int:
        if remaining == 0:
            return count
        if remaining not in memo:
            y = sys.maxsize
            for coin in filter(lambda x: x <= remaining, coins):
                y = min(y, self._loop(coins, remaining - coin, 1, memo))

            memo[remaining] = (y + count) if y < sys.maxsize else y

        return memo[remaining]

对于每个递归调用,修复被重置为count1

陈翰林
2023-03-14

根据您使用memo的方式,memo[x]意味着包含总计x美分所需的最小硬币数量。然而,事实并非如此。

让我们看看递归堆栈:

remaining = 4, count = 0, y = maxsize, take coin 1:
    remaining = 3, count = 1, y = maxsize, take coin 1:
        remaining = 2, count = 2, y = maxsize, take coin 1:
            remaining = 1, count = 3, y = maxsize, take coin 1:
                remaining = 0, count = 4, RETURN 4
            y = 4, memo[1] = 4, RETURN 4
        remaining = 2, count = 2, y = 4, take coin 2:
            remaining = 0, count = 3, RETURN 3
        y = 3, memo[2] = 3, RETURN 3
    remaining = 3, count = 1, y = 3, take coin 2:
        remaining = 1, count = 2, memo[1] exists, RETURN 4
    y = 3, memo[3] = 3, RETURN 3
remaining = 4, count = 0, y = 3, take coin 2:
    remaining = 2, count = 1, memo[2] exists, RETURN 3
y = 3, memo[4] = 3, RETURN 3

看到问题了吗<代码>备忘录中的值不正确<代码>备忘录[1]应为1,但代码将其设置为4。类似地,memo[3]应该是2,但代码将其设置为3。

要像您正在使用的那样使用memo数组,从下到上工作会容易得多:从一个基本条件(memo[0]=0)开始,计算memo[1]、memo[2]、。。。备注[金额]基于先前计算的值。

 类似资料:
  • 我现在正在研究leetcode322。换硬币,问题如下: 您将获得一个整数数组,表示不同面额的硬币,以及一个整数金额,表示总金额。 返回您需要的最少数量的硬币,以弥补该金额。如果这些硬币的任何组合都无法弥补这一数额,则返回-1。 你可以假设每种硬币的数量是无限的。 例1: 输入:硬币=[1,2,5],数量=11输出:3说明:11=5 1 例2: 输入:硬币=[2],金额=3输出:-1 例3: 输入

  • 我目前正在研究leetcode上的硬币兑换动态规划问题--https://leetcode.com/problems/coin-change/. 下面是问题陈述: 我试图实现一种自上而下的记忆方法,在这种方法中,我保留了一个长度数量的数组,其中每个索引表示我可以用来生成该数量的最小硬币数量。 以下是我的Java代码: 我认为这是解决这个问题的正确的动态编程方法,但是我在leetcode上超过了时间

  • 我在理解动态规划中的硬币兑换问题时遇到了一个小问题。简单地说,我必须用最少数量的硬币来兑换一笔钱。 我有n种面值为1=v1的硬币

  • 以人民币的硬币为例,假设硬币数量足够多。要求将一定数额的钱兑换成硬币。要求兑换硬币数量最少。 思路说明: 这是用贪婪算法的典型应用。在本例中用python来实现,主要思想是将货币金额除以某硬币单位,然后去整数,即为该硬币的个数;余数则做为向下循环计算的货币金额。 这个算法的问题在于,得出来的结果不一定是最有结果。比如,硬币单位是[1,4,6],如果将8兑换成硬币,按照硬币数量最少原则,应该兑换成为

  • 这是hackerrank(https://www.hackerrank.com/challenges/coin-change)的硬币更换问题。它要求计算使用给定面值的硬币对N进行更改的方法总数。 例如,有四种方法可以使用面额为1、2和3的硬币兑换4。它们是-

  • 我试图使用贪婪算法来计算在JavaScript中达到一定数量所需的最低硬币数量 返回结果将是一个数组,由每个级别的硬币数量组成 我决定做一个函数来解决这个问题,但它不起作用 calculateChange函数包含两个参数:硬币值数组和金额。 第一步是初始化一个sum变量,该变量显示已调度的更改量。我还将创建一个数组变量,该变量将保存某个硬币的分配次数。 为此,我将迭代coins数组并将所有值设置为