访谈:换取n美分(任意面额)

时间:2014-09-15 16:50:09

标签: algorithm

这个问题是在采访中日益困难的问题的一部分。它开始如此简单:

  

(1)假设无限量供应硬币(通常为1,5,10,25美分面额)。给定 n 美分,是否总有办法使用正常面额对其进行更改?

是的,因为便士将所有可能的值除以 n 分。

  

(2)好,现在写一个接受 n (正)美分的程序,并返回一种可能的改变方法

返回 n 便士。

  

(3)自作聪明。如果您想最大限度地减少进行更改所需的硬币数量该怎么办?

从最大面额 d_i 开始,并取最大数量,使其不超过 n m_i 。取 n - (d_i)(m_i)并重复下一个最大面额。

  

(4)好,你能证明这个解决方案是最优的吗?

是的,{blah,blah}

  

(5)好的,* smirk *,现在如果除了 n 美分之外你还得到一个由任意面额组成的任意大小的数组?您可以假设每个面额在数组中只出现一次,并且所有面额都是正数

我最初的想法只是对面额数组进行排序,并应用与(4)中相同的逻辑。幸运的是,在我传达这个之前,我抓住了自己并意识到它不会起作用。但是现在我意识到我在泡菜中。

我的下一个想法是将sum-subset问题应用于 n 的每个除数,但是意识到这可能是过度的。我最终提供的解决方案只是使用Change-making problem,并在找到某些解决方案时将其短路。我觉得必须有一个更聪明的方法来做到这一点..

问题简化为:给定不同自然数的有限集 S ,找到 S 元素的线性组合,其中(1)与另一个元素相加自然数 n ,(2)最小化lin.combination中系数的总和

3 个答案:

答案 0 :(得分:4)

实际上这个问题已被研究为 Canonical coin systems ,我们甚至得到了一篇关于如何确定给定的硬币系统是否能支持贪婪解决方案的论文。原始论文可能会为您提供一些见解:Canonical coin systems for change-making problems

或者,您可以谷歌关键词" Canonical coin systems"了解更多信息。

答案 1 :(得分:0)

如果不可能,请d[pos][sum]只使用第一个sum denonimations或Infinity来改变pos钱所需的最小硬币数

a[i]成为硬币i的变形

可以递归地理解。规则1)2)将是递归的基础。

1)d[any pos][0]=0(我们不能在没有硬币的情况下退货)

2)d[1][each sum] = if(a [1]!= sum)Infinity else 1(只有当它具有denonimation sum时,我们才可以用一个硬币进行总和更改

3)否则:

我们可以选择当前点进行更改或不选择

d[pos][sum]=min(choose,d[pos-1][sum])其中

choose=d[pos-1][sum-a[i]]如果sum> = a [i],则无限

如果我们不选择硬币数字pos,我们尝试使用pos-1硬币进行相同的更改。因此,d[pos-1][sum]

如果我们选择硬币数pos,那么我们只需要通过pos的denonimation对小于当前的和进行改变。 d[pos-1][sum-a[i]]

但是,只有当它的变焦小于或等于当前总和时,我们才能选择硬币数量


在实际解决方案中

a)递归应该用循环

代替

b)我们应该存储was[pos][sum] - 如果计算了值d[pos][sum]

当我们尝试计算d[pos][sum]

如果was[pos][sum]==true只是返回它。 (该值已经计算在内)

else:根据步骤1-3计算并将was[pos][sum]设置为true

答案 2 :(得分:0)

有一个简单的答案,根据n给出伪多项式时间和空间(即运行时间和内存使用与n成比例而不是输入大小,即log n),并且更难,但更多有用的答案可以让你获得固​​定面额的真正多项式时间。

制作一个大小为n的数组A.该数组存储每k = 1到n需要k美分所需的最小硬币数,其中如果不可能得到k美分,则A [k] = -1。你可以从k = 1到n依次填写这个数组,如果k是你的面额之一,记录A [k] = 1,否则记录A [k] = M + 1,其中M是A [k的最小值 - C]超过所有面额C(和A [k] = -1,如果所有k - C都不是正数或A [k - C] = -1)。然后,一旦你到达n,你可以从n开始返回数组并减去每个面额,看看哪个面额给你最佳答案,追溯用于形成最佳解决方案的所有硬币。

这是一个简单的答案。现在,与面额相比,非常大的n的硬答案是弄清楚什么时候你可以采取捷径,并且只需要拿出最大面额硬币一段时间,直到剩余的总分数降到某个值以下。我不知道如何解决这个问题,但它是可能的,并且值总是存在的,一旦你搞清楚了,那么无论n有多大,你所要做的就是计算多少首先使用的最大硬币(O(log n)时间),然后在低于该值时解决(如果您考虑固定的面额,则为恒定时间,或者如果面额,则取决于面额(但不是n)的运行时间)不固定)。

相关问题