一道面试题。
贝壳国法定货币是贝壳。贝壳特性如下:
1:贝壳以颜色区分面值。
2:较大面值一定是较小面值的整数倍。(例如,1,2,4,12)
3:贝壳面值都是正整数
贝壳国旅游业发达,国外游客游历贝壳国需要携带贝壳币,等额RMB换取等额贝壳币。贝壳币可以从ATM机中换取。
贝壳国ATM机换取规则如下:
同等金额下,使用尽可能少的币种组合。
例如:假设贝壳国有只有3中面额货币,1,2,4。某游客换取5RMB,可能的组合有:
1)5个1
2)2个2 + 1个1
3)1个4 + 1个1
4)2个2 + 1个1
5) 3个1 + 1个2
显然,1个4 + 1个1的组合是最少币种组合。
问题1:假设面值是(1,2,4,12),游客至少需要投入多少RMB才能推测出贝壳国所有货币的颜色代表的面额?
问题2:有没有可能存在某种面值组合,游客一次投入RMB无法推测所有货币的面额?若存在,举出例子。
问题3:设计程序分析,哪些组合是可以一次性推测出的,哪些不可以。
上面的又错了,- -!,跟 @TinaRose 交流后发现自己之前确实弄错了。难怪一直觉得不太对劲,肯定是忽略了什么问题,现在终于知道了!
问题1:答案确实是
12+4+2+1=19元
,方法是分4次兑换,先换12元
,再换4元
,再换2元
,最后换1元
,这样就能确定所有贝壳币的颜色了。因为没说只能换1次,所以这样分开兑换所花的钱最少。问题2:存在,例如
1, 2, 4
这种组合,无论一次兑换多少钱,都无法做到每种贝壳币数量各不相同。因为,首先1元
的只能是1枚(超过1枚的部分必然会合并到2元
上去),所以2元
的必然要大于1枚,但这也是不可能的,因为这时超过的部分也会合并到4元
上去。所以无论如何也无法区分出1元
和2元
问题3:
分析:
有面值组合
(a1, a2, ..., am)
,则每次兑换所投入的RMB
总额可以表示为:a1*n1 + a2*n2 + a3*n3 + ... + am*nm
如果可以一次性区分出所有面值的颜色,那么
n1, n2, n3, ..., nm
必然各不相同,并且对于任何一种面值ak
,ak*nk
的值必然小于a[k+1]
(否则就会合并到更大的面值上去)。设
a[k+1]/ak
的比值为qk
,则:根据前面任意的
k
都必然有ak*nk<a[k+1]
的结论,可以知道n1, n2 ... n[k-1]
全部小于qk
(这个结论还反映出一点,即对最后一项nm
是没有要求的,实际上也确实如此,nm
的值上不封顶,如果需要可以是任意大的值)。根据以上结论,可以设计出以下算法:
我们可以用一个
n的备选集合
来作为检查集合,集合初始化为(1, 2, 3, ..., m-1)
。然后遍历比值
q
的集合(q1, q2, ..., q[m-1])
,对每一个qk
,执行以下检查:(1) 当
qk >= k
时,将n[qk-1]
(注意不是n[q[k-1]]而是n[(qk)-1]
)标记为“已占用”。如果n[qk-1]
已经被占用,则进行与第2步相同的操作(2) 当
qk < k
时,从n1~n[k-1]
之间找一个未被占用的,将其标记为“已占用”。如果找不到,则表示此面值组合无法一次性推断出来。如果遍历结束,未出现“找不到”的情况,则表示此面值组合可以一次性推断出来。如果能一次性推断出来,那么遍历的过程也是找到答案的过程,按顺序将被占用的
n
的值写出来就是答案(但可能不是最优的答案)。例如对于
(1, 2, 4)
这个面值组合,其比值集合为(2, 2)
,先看q1
,为2
,我们将n1
标记为“已占用的”,再看q2
,为2
,由于这时n1
已被占用,因此此组合无法一次性推断出来。再看看
(1, 2, 8)
这个,其比值集合为(2, 4)
,q1
会把n1
占掉,q2
会把n3
占掉,两者没有冲突,所以这个组合是可以一次性推断出来的,而(1*1+2*3+8*?)
就是其中的一种方法(?表示随便选一个不与前面有冲突的即可,例如2
)