我在采访中被问到这个问题。 给出一个“N' N'硬币,它们的值在一个数组A []中,返回所需的最小硬币数量,以及“S' (你可以使用你想要的硬币)。如果无法汇总到' S',则返回-1 请注意,我可以多次使用相同的硬币。
示例:
输入#00:
硬币面额:{1,3,5}
所需金额(S):11
输出#00:
3
说明: 所需的最小硬币数量为:3 - 5 + 5 + 1 = 11;
除Sorting the array and start it by both ends
之外,还有其他更好的方式吗?
答案 0 :(得分:0)
您似乎正在考虑一种简单的贪婪方法,并不总能产生最佳结果。如果你从两端开始详细说明你究竟是什么意思,我可能会想出一个反例。
采用dynamic programming方法取自here:
让
C[m]
为d1
金额更改所需的最低面额硬币d2
,dk
,...,m
。在为m
金额进行更改的最佳解决方案中,必须存在一些第一枚硬币di
,其中di < m
。此外,解决方案中剩余的硬币本身必须是对m - di
进行更改的最佳解决方案。因此,如果
di
是进行m
金额更改的最佳解决方案中的第一个硬币,那么C[m] = 1 + C[m - di]
,即一个di
硬币加C[m - di]
}硬币以最佳方式更改m - di
金额。我们不知道哪枚硬币di
是第一枚硬币;但是,我们可以检查所有n
这样的可能性(受di < m
的约束),并且根据定义,最优解的值必须对应于1 + C[m - di]
的最小值。 / p>此外,当对0进行更改时,最佳解决方案的值显然是0个硬币。因此,我们有以下重复。
C[p] = 0 if p = 0 min(i: di < p) {1 + C[p - di]} if p > 0
答案 1 :(得分:0)
寻路算法(Dijkstra,A *,中间会议等)可能适用于这样的图:
0
1/|\5
/ |3\
/ | \
1 3 5
1/|\51/| ...
/ |3\/ |3
/ | /\ |
2 4 6
....
其他方式是递归二分法。比方说,如果我们不能用一枚硬币获得总和S,我们就会开始尝试递增金额(S / 2,S / 2)......(S-1,1),直到我们找到合适的硬币或达到S = 1