使用 Java 8
,我试图找出一种算法/适当的解决方案,以查看如何在特定分配的预算内存储带有可购买物品的 List<String>
。
假设,一个 Map<String, Double>
包含以下键/值:
Map<String, Double> menu = new HashMap<>();
menu.put("Fruit", 2.15);
menu.put("Fries", 2.75);
menu.put("Salad", 3.35);
menu.put("Wings", 3.55);
menu.put("Mozzarella", 4.20);
menu.put("Plate", 5.80);
考虑具有以下签名的方法:
public static List<List<String>> getListOfBuyableItems(
Map<String, Double> menu, double budget)
需要执行以下规则:
-
预算 = 4.30,则返回的 ArrayList 为: ```
[["Fruit", "Fruit"]] -
预算 = 5.50,则返回的 ArrayList 为: ```
[["Fries", "Fries"], ["Fruit", "Salad"]] -
Budget = 2.15,则返回的ArrayList为: ```
[["Fruit"]] -
- *
这是我想出的,但我似乎无法弄清楚如何使用递归和/或不同的方法来解决这个问题:
public static List<List<String>> getBuyableItems(
Map<String, Double> menu, double budget) {
if (menu.isEmpty() || budget < 1) {
return Collections.emptyList();
}
List<List<String>> buyableItems = new ArrayList<>();
double amount = budget;
for (Map.Entry<String, Double> menuItem : menu.entrySet()) {
System.out.println(menuItem.getKey() + " $" + menuItem.getValue());
if (budget > menuItem.getValue()) {
buyableItems.add(menuItem.getKey());
keepBuying(menu, budget);
amount = budget - menuItem.getValue();
}
}
return buyableItems;
}
public static void keepBuying(Map<String, Double> menu, double budget) {
if (budget > 0.00) {
for (Map.Entry<String, Double> menuItem : menu.entrySet()) {
budget -= menuItem.getValue();
}
}
}
如何使用递归或其他解决方案解决此问题?
我现在只是好奇使用以下方法解决这个问题:
- 使用 for 或 while 循环
- Java 8 功能:流和 Lambda
这个问题是硬币找零问题的直接应用。
可以递归地构造动态规划解决方案,如下所示:
对于每个项目,解决方案是两种情况的组合:
1.该项目包含在解决方案中
2.该项目被排除在外
对于第一种情况,解决方案是
getBuyableItems(Menu, budget - item.value)
的结果,而对于第二种情况,解决方案是getBuyableItems(Menu after removing {item}, budget)
。但是,此解决方案效率不高,并且可能会导致大型案例的内存问题。还有另一种解决方案使用了一种称为记忆的技术。
对于这个问题,我们可以定义一个包含所有可能子问题的表格,并逐步构建该表格,直到我们到达最终位置的解决方案。表中的每个单元格代表一个从 0 开始到请求预算的案例。最终,每个单元将保存相应子问题的解决方案。例如,table[215] 将有一个列表 {"Fruit"}。这种解决方案的优点是我们不需要每次需要时都计算相同的子问题。
通过获取 table[j-i] 中的所有解决方案并将项 i 键添加到这些解决方案,可以通过项 i(给定 j >= i)构造 table[j] 的解决方案。