【问题标题】:Algorithm fails for coin change硬币找零算法失败
【发布时间】:2015-02-01 07:27:29
【问题描述】:

我正在尝试从 coursera 的 scala 课程中构建我的最后一篇作业,但是我的算法似乎失败了。但是我不明白为什么它失败以及为什么它返回 0。

注意我并不是要解决这个问题。我想解释一下代码发生了什么以及它失败的原因。

def countChange(money: Int, coins: List[Int]): Int = {
    def cc(amount: Int, list: List[Int]): Int = {
      println(amount, list);
      if (amount == 0) 1
      if (amount < 0 || list.isEmpty) 0
      else cc(amount - list.head, list) + cc(amount, list.tail)
    }

    cc(money, coins)
}

逻辑是,你可以给给定数量找零的方式的数量等于你可以使用第一种硬币+你可以找零的方式的数量下一种硬币。这导致了一个计算所有方式的递归函数。这是我的逻辑,这也是我试图构建的,但这就是它返回的内容:

   (10,List(2, 3, 5))
(8,List(2, 3, 5))
(6,List(2, 3, 5))
(4,List(2, 3, 5))
(2,List(2, 3, 5))
(0,List(2, 3, 5))
(-2,List(2, 3, 5))
(0,List(3, 5))
(-3,List(3, 5))
(0,List(5))
(-5,List(5))
(0,List())
(2,List(3, 5))
(-1,List(3, 5))
(2,List(5))
(-3,List(5))
(2,List())
(4,List(3, 5))
(1,List(3, 5))
(-2,List(3, 5))
(1,List(5))
(-4,List(5))
(1,List())
(4,List(5))
(-1,List(5))
(4,List())
(6,List(3, 5))
(3,List(3, 5))
(0,List(3, 5))
(-3,List(3, 5))
(0,List(5))
(-5,List(5))
(0,List())
(3,List(5))
(-2,List(5))
(3,List())
(6,List(5))
(1,List(5))
(-4,List(5))
(1,List())
(6,List())
(8,List(3, 5))
(5,List(3, 5))
(2,List(3, 5))
(-1,List(3, 5))
(2,List(5))
(-3,List(5))
(2,List())
(5,List(5))
(0,List(5))
(-5,List(5))
(0,List())
(5,List())
(8,List(5))
(3,List(5))
(-2,List(5))
(3,List())
(8,List())
(10,List(3, 5))
(7,List(3, 5))
(4,List(3, 5))
(1,List(3, 5))
(-2,List(3, 5))
(1,List(5))
(-4,List(5))
(1,List())
(4,List(5))
(-1,List(5))
(4,List())
(7,List(5))
(2,List(5))
(-3,List(5))
(2,List())
(7,List())
(10,List(5))
(5,List(5))
(0,List(5))
(-5,List(5))
(0,List())
(5,List())
(10,List())
0

您可以看到它返回 0,即使从打印的调用中可以看出它所采取的步骤似乎正是我的逻辑试图实现的目标。

这是主函数中函数的调用:

 println ("" + countChange(10,List(2,3,5)))

不要给我可以复制和粘贴的烘焙代码。我想知道我的逻辑有什么问题。

【问题讨论】:

  • +1 不是要求解决方案,而是要求您的代码失败的原因。

标签: algorithm scala


【解决方案1】:

您缺少else

  if (amount == 0) 1   // This value is thrown away
  if (amount < 0 || list.isEmpty) 0
  else cc(amount - list.head, list) + cc(amount, list.tail)

只需在第二个 if 之前添加它就可以了。

(如果不清楚,只返回最后一个if/else的结果,所以在

if (a) 1
if (b) 2
if (c) 3
else 4

只有最后两行重要。如果您想选择其中一个选项,

if (a) 1
else if (b) 2
else if (c) 3
else 4

是你需要的。)

【讨论】:

  • 这是一个解决方案,不是解释。
  • 通过解释为什么该失败会导致问题,您在编辑中已经这样做了。
  • @JAB - 我认为人们知道 if/else 是如何工作的,但无论如何,既然编辑在那里,这些 cmets 就不需要了,所以我要删除我的。
  • @RexKerr 我怎么能错过这个。
【解决方案2】:

您的错误在代码的递归部分中:

 cc(amount -list.head, list) + cc(amount, list.tail)

如果您查看第一部分,您将再次传递整个列表,而不会删除 head。这意味着您得到答案的唯一方法是,金额是否能被当前列表头部位置的硬币完全整除。

【讨论】:

  • 这也是一个错误,但我打算让他们发现,一旦他们有一个返回值可以使用:)
  • @wheaties 这是算法的重点。您可以找零的方式数量等于您使用第一枚硬币可以找零的方式数量加上使用其余硬币的方式数量。后者最终将以同样的方式结束
  • @Bula 仅当您被允许无限数量地使用每种类型的硬币时。如果是这样,那我就错了。如果不是,那么这是您的算法中的错误。
  • 从 Coursera 的实际问题中可以清楚地看出,该列表是硬币面额的。每个硬币的数量不限。
  • @wheaties 是的,我应该给你这个额外的细节。对不起
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-18
  • 1970-01-01
  • 2023-03-02
  • 2013-12-09
  • 2016-01-25
相关资源
最近更新 更多