题目
这是今年华为校招的一道测试题,题目为:
我们知道人民币有1、2、5、10、20、50、100这几种面值。现在给你n(1≤n≤250)元,让你计算换成用上面这些面额表示且总数不超过100张,共有几种。比如4元,能用4张1元、2张1元和1张2元、2张2元,三种表示方法。
思路
根据{1、2、5、10、20、50、100}构建一张 n行7列的图,利用图的深度优先收索算法求解。
代码:
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
Main main = new Main();
int[] a = { 1, 2, 5, 10, 20, 50, 100 };
int n = 5;
main.f1(a, n);
}
private void f1(int[] a, int n) {
if (n <= 0) {
System.out.println(0);
return;
}
HashSet<String> arr = new HashSet<String>();
ArrayList<Integer> list = new ArrayList<Integer>();
getResult(a, n, 0, arr, list);
System.out.println("共有:" + arr.size() + "种\n分别是:");
for (String str : arr) {
System.out.println(str);
}
}
private void getResult(int[] a, int n, int sum, HashSet<String> arr,
ArrayList<Integer> list) {
if (sum > n) {
return;
}
if (sum == n && arr.size() <= 100) {
StringBuffer sb = new StringBuffer();
Collections.sort(list); // 排序去重
for (int i = 0; i < list.size(); i++) {
sb.append(list.get(i) + " ");
}
arr.add(sb.toString());
return;
}
for (int i = 0; i < a.length; i++) {
sum += a[i];
list.add(a[i]);
// 深度优先
getResult(a, n, sum, arr, list);
// 回溯
sum -= a[i];
list.remove((Object) a[i]);
}
}
}
结果:
共有:4种
分别是:
1 1 1 1 1
1 2 2
5
1 1 1 2