这是一个采访问题:
给定金额,比如167.37美元,找到使用货币中可用面额产生此金额变化的所有可能方法?
任何想到空间和时间效率算法和支持代码的人,请分享。
这是我写的(工作)代码。我试图找到这个的运行时间,任何帮助表示赞赏
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
public class change_generation {
/**
* @param args
*/
public static void generatechange(float amount,LinkedList<Float> denominations,HashMap<Float,Integer> useddenominations)
{
if(amount<0)
return;
if(amount==0)
{
Iterator<Float> it = useddenominations.keySet().iterator();
while(it.hasNext())
{
Float val = it.next();
System.out.println(val +" :: "+useddenominations.get(val));
}
System.out.println("**************************************");
return;
}
for(Float denom : denominations)
{
if(amount-denom < 0)
continue;
if(useddenominations.get(denom)== null)
useddenominations.put(denom, 0);
useddenominations.put(denom, useddenominations.get(denom)+1);
generatechange(amount-denom, denominations, useddenominations);
useddenominations.put(denom, useddenominations.get(denom)-1);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
float amount = 2.0f;
float nikle=0.5f;
float dollar=1.0f;
float ddollar=2.0f;
LinkedList<Float> denominations = new LinkedList<Float>();
denominations.add(ddollar);
denominations.add(dollar);
denominations.add(nikle);
HashMap<Float,Integer> useddenominations = new HashMap<Float,Integer>();
generatechange(amount, denominations, useddenominations);
}
}
答案 0 :(得分:4)
编辑
这是组合/子集问题的具体示例,在此处回答。
Finding all possible combinations of numbers to reach a given sum
---我保留下面的答案(因为它对某人有用),但是,诚然,这不是这个问题的直接答案---
原始回答
最常见的解决方案是动态编程:
首先,您找到了更改1的最简单方法,然后使用该解决方案对2,3,4,5,6等进行更改....在每次迭代中,您“检查”是否可以“向后”并减少答案中的硬币数量。例如,最多为“4”,您必须添加便士。但是,一旦你达到“5”,你可以删除所有的便士,而你的解决方案只需要一枚硬币:镍。但是,直到9,你再次必须添加便士等等。
但是,动态编程方法并不能保证快速。
或者,你可以使用贪婪的方法,在那里你不断挑选最大的硬币。这非常快,但并不总能为您提供最佳解决方案。但是,如果你的硬币是1 5 10和25,那么贪婪的工作完美,并且比线性编程方法快得多。
答案 1 :(得分:2)
Memoization(有点)是你的朋友。 C中的一个简单实现:
unsigned int findRes(int n)
{
//Setup array, etc.
//Only one way to make zero... no coins.
results[0] = 1;
for(i=0; i<number_of_coins; i++)
{
for(j=coins[i]; j<=n; j++)
{
results[j] += results[j - coins[i]];
}
}
return results[n];
}
所以,我们在这里真正做的是说:
1)我们制作0币的唯一可行方法是0(这是我们的基本情况)
2)如果我们试图计算m值,那么让我们检查每个硬币k。只要k <= m,我们就可以在解决方案中使用该硬币k
3)好吧,如果我们可以在解决方案中使用k,那么我们不能只采用(m-k)的解决方案并将其添加到我们当前的总数中吗?
答案 2 :(得分:0)
我试着在现实生活中对此进行建模。
如果你在收银台并且你知道你必须找到167.37美元,那么你最初可能会认为200美元是“最简单”的投标,只有两个钞票。然后,如果我有它,我可以考虑170美元,即100美元,50美元和20美元(三个音符)。看看我要去哪里?
更正式的是,尝试使用最少数量的纸币/硬币进行过度投标。这比完整的可能性更容易列举。
答案 3 :(得分:0)
不要使用花车,即使最小的不准确也会破坏你的算法。
从最大到最低的硬币/钞票。对于每个可能的量,递归调用该函数。当没有剩余硬币时,将其余硬币支付给其中并打印解决方案。这就是它在伪C中的表现:
#define N 14
int coinValue[N]={20000,10000,5000,2000,1000,500,200,100,50,20,10,5,2,1};
int coinCount[N];
void f(int toSpend, int i)
{
if(coinValue[i]>1)
{
for(coinCount[i]=0;coinCount[i]*coinValue[i]<=toSpend;coinCount[i]++)
{
f(toSpend-coinCount[i]*coinValue[i],i+1);
}
}
else
{
coinCount[i]=toSpend;
print(coinCount);
}
}
答案 4 :(得分:0)
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
public class change_generation {
static int jj=1;
public static void generatechange(float amount,LinkedList<Float> denominations,
HashMap<Float,Integer> useddenominations) {
if(amount<0)
return;
if(amount==0) {
Iterator<Float> it = useddenominations.keySet().iterator();
while(it.hasNext()) {
Float val = it.next();
System.out.println(val +" :: "+useddenominations.get(val));
}
System.out.println("**************************************");
return;
}
for(Float denom : denominations) {
if(amount-denom < 0)
continue;
if(useddenominations.get(denom)== null)
useddenominations.put(denom, 0);
useddenominations.put(denom, useddenominations.get(denom)+1);
generatechange(amount-denom, denominations, useddenominations);
useddenominations.put(denom, useddenominations.get(denom)-1);
}
}
public static void main(String[] args) {
float amount = 2.0f;
float nikle=0.25f;
float dollar=1.0f;
float ddollar=2.0f;
LinkedList<Float> denominations = new LinkedList<Float>();
denominations.add(ddollar);
denominations.add(dollar);
denominations.add(nikle);
HashMap<Float,Integer> useddenominations = new HashMap<Float,Integer>();
generatechange(amount, denominations, useddenominations);
}
}