您的任务看起来像硬币交换问题,描述为here。
但不是简单地获取您想要枚举结果的可能排列的数量,因此需要更改代码。
例如,我的解决方案在 Java 8 中可能如下所示:
import java.util.*;
import java.util.stream.Collectors;
public class Solution {
private List<Integer> rooms;
private int numberToCheck;
private Map<Integer, Set<List<Integer>>> cache;
public Solution(List<Integer> rooms, int numberToCheck) {
this.numberToCheck = numberToCheck;
this.cache = new HashMap<>();
this.rooms = rooms;
}
public Set<List<Integer>> solve() {
return count(numberToCheck);
}
private Set<List<Integer>> count(int currentNumber) {
if (currentNumber <= 0) {
return Collections.emptySet();
}
if (cache.containsKey(currentNumber)) {
return cache.get(currentNumber);
}
Set<List<Integer>> currentSolutions = new HashSet<>();
cache.put(currentNumber, currentSolutions);
for (Integer room : rooms) {
if (currentNumber == room) {
currentSolutions.add(Collections.singletonList(room));
}
Set<List<Integer>> previousSolutions = count(currentNumber - room);
for (List<Integer> previousSolution : previousSolutions) {
List<Integer> solution = new ArrayList<Integer>() {{
addAll(previousSolution);
add(room);
}};
Collections.sort(solution);
currentSolutions.add(solution);
}
}
return currentSolutions;
}
public static void main(String[] args) {
List<Integer> rooms = new ArrayList<Integer>() {{
add(1);
add(2);
add(3);
}};
int n = 5;
Solution solution = new Solution(rooms, n);
Set<List<Integer>> results = solution.solve();
System.out.println("Total results: " + results.size());
System.out.println("Simple results: " + results);
List<List<Integer>> sortedResults = new ArrayList<List<Integer>>() {{
addAll(results);
}};
sortedResults.sort((list1, list2) -> -Integer.compare(list1.size(), list2.size()));
System.out.println("Sorted results: " + sortedResults);
System.out.println("Line by line:");
sortedResults.forEach(list -> {
List<String> stringList = list.stream().map(Object::toString).collect(Collectors.toList());
System.out.println(String.join(",", stringList));
});
}
}
输出会是这样的:
Total results: 5
Simple results: [[1, 2, 2], [1, 1, 3], [2, 3], [1, 1, 1, 1, 1], [1, 1, 1, 2]]
Sorted results: [[1, 1, 1, 1, 1], [1, 1, 1, 2], [1, 2, 2], [1, 1, 3], [2, 3]]
Line by line:
1,1,1,1,1
1,1,1,2
1,2,2
1,1,3
2,3
这种方法使用动态编程技术(或记忆化)来存储中间结果以避免不必要的重新计算。方法count对唯一编号只计算一次,房间也只枚举一次。因此,假设房间数量为 k,计算被称为 nk 次。如果我们只需要计算可能的结果,算法复杂度将是 O(kn)。因此,要计算给定任务的结果计数,需要 3*5=15 次迭代。这是非常快的。
但需要枚举所有可能的解决方案,其数量可能会组合(根据输入)增加复杂性,消耗时间和空间,并且有一些排序操作会增加额外的开销,这可能需要嗯!最坏情况下的操作。
这种方法在我的 PC 上运行得非常快,n=200 具有相同的房间列表 {1,2,3},并且需要几秒钟才能显示结果。