我正在接受一些练习面试的问题,这一直困扰着我。这是问题:
给定硬币1c,7c,13c和19c返回具有所需硬币数量最少的字符串>表示X的输入。
现在,我已经很容易地解决了这个问题,之后它就像1c,5c,10c和25c这样的简单面额。这只是一个简单的贪心算法。为此,我认为这将是某种排列问题,但我不知道如何获得最低限度。有任何想法吗?这是我的一些伪代码:
String coinDenominations(double amount, String coins)
{
if(amount > .19) coinDenominations(amount - .19, coins + "19 ");
if(amount > .13) coinDenominations(amount - .13, coins + "13 ");
if(amount > .07) coinDenominations(amount - .07, coins + "7 ");
if(amount > .01) coinDenominations(amount - .01, coins + "1 ");
if(amount == 0) System.out.println(coins);
}
我的排列很生疏,但我认为这会输出可能的组合。我怎么能找到最小的金额呢?有没有更好的非递归方式呢?
答案 0 :(得分:0)
我认为可以这样做。
金额是x。硬币是1c,7c,13c& 19C。
算法如下。
x = x * 100;
need_19 = x / 19;
y = x%19;
need_13 = y / 13;
y = y%13;
need_7 = y / 7;
y = y%7;
need_1 = y;
total_coins = need_19 + need_13 + need_7 + + need_1;
答案 1 :(得分:0)
我认为我们可以这样写:
String coinDenominations(double amount){
int[] coinDenom = new int[] {19,13,7,1};
int amountInCents = amount*100;
String coinDenomString = "";
for(int i=0; i< coinDenom.length; i++){
coinDenomString = coinDenomString + ((int)(amountInCents/coinDenom[i]))
+ "of +" coinDenom[i] + "coins";
amountInCents = amountInCents % coinDenom[i];
}
return coinDenomString;
}
我相信,上面的也可以转换为递归。
答案 2 :(得分:0)
正如this answer中所提到的,某些硬币组合可能适用于贪婪的算法,但并不能保证贪婪会为所有硬币组合提供最佳组合。
Python中的一种详尽的递归解决方案(伪代码的理想语言)如下所示。
请注意,这会为您提供排列而不是组合,但是,如果您想过滤掉重复项(就组合而言),则在创建列表后进行排序和过滤会很简单。
另请注意,对于较大金额而言,这可能相当可怕。例如,虽然对于像27或75这样的输入值,它在一秒钟之内,但是在我感到无聊并取消之前,1024的输入至少需要几分钟。
import sys
oldcount = 99999999
lst = []
def recurse (str, amt, count):
global oldcount
global lst
if amt < 0: return
if count > oldcount: return
if amt == 0:
if count < oldcount:
print "====="
lst = []
oldcount = count
if count == oldcount:
lst.append (str)
return
recurse ("%s 19" % str, amt - 19, count + 1)
recurse ("%s 13" % str, amt - 13, count + 1)
recurse ("%s 7" % str, amt - 7, count + 1)
recurse ("%s 1" % str, amt - 1, count + 1)
recurse ("", int (sys.argv[1]), 0)
#for seq in lst: print seq
print "%d permutations" % len (lst)
注意,对于面额{1, 7, 13, 19}
(这种特殊情况),贪婪算法 是最好的,其“证据”是(a):
对于任何值1到6,你有使用那么多1
个硬币,这就是贪婪算法给你的。
对于任何7到12的值,您可以使用那么多1
个硬币,也可以使用7
来减少7个1
个硬币。贪婪算法为你提供了后一种情况,这是正确的,因为最好带走七个1
硬币并添加一个7
硬币 - 它会将硬币数量减少六个。
对于值13到18,您无法使用13
和7
,因为这将至少为20
,因此您会遇到13/1
混合或7/1
混合(所有1
硬币出于与上一段中相同的原因 - 为单个1
硬币交换13 13
个硬币是一个大幅减少)。显然,13值的最佳选择是单个13
硬币,但可以使用7/7
或13/1
(两个硬币)实现14。然后,值15到18只添加了1
个硬币。
同样,19值是单个硬币19
,而20值可以由19/1
或13/7
表示。从21到37(在19/19
值38之前)的值为19
加上前三段中的最小混合。
因此,由于所选择的值(1
和7
不同,7/7
== 13/1
,7/7/7
== 19/1/1
,13/7
== 19/1
等等,贪婪的算法运行得很好(我不相信那些值是随机选择的,这太方便了。)
最小硬币计数表如下:
Value Count Possibilities
1 1 1
2 2 1x2
3 3 1x3
4 4 1x4
5 5 1x5
6 6 1x6
7 1 7
8 2 7,1
9 3 7,1x2
:
12 6 7,1x5
13 1 13
14 2 13,1 or 7x2
15 2 13,1x2 or 7x2,1
:
18 6 13,1X5 or 7x2,1x4
19 1 19
20 2 19,1 or 13,7
21 3 19,1x2 or 13,7,1 or 7x3
:
等等。
(a)不是正式证明,但我确信我是对的,我会向第一个向我展示的人提出20个问题/答案一个反例(提供问题和答案当然不是完全垃圾 - 我必须认为它们是有用的,以免破坏投票过程。)