如何解决餐厅菜单和收据的最佳解决方案
我最近遇到了这个问题。
” 我去过一家餐馆点菜,但我忘记了过去的点菜。我只记得我花了多少钱。
从以下菜单和收据值列表中,确定我可以订购的东西。 '''
primary_menu = { 蔬菜三明治:6.85, '额外的蔬菜':2.20, '鸡肉三明治':7.85, '额外的鸡':3.20, '奶酪':1.25, “筹码”:1.40, '玉米片':3.45, '苏打水':2.05, }
reversed_primary_menu = { 6.85:“素食三明治”, 2.20:“额外的蔬菜”, 7.85:“鸡肉三明治”, 3.20:“额外的鸡肉”, 1.25:“奶酪”, 1.40:“筹码”, 3.45:“玉米片”, 2.05:“ soda”, }
''' 这是我在餐厅订的9种不同订单的收据清单 ''' 收据= [4.85,11.05,13.75,17.75,18.25,19.40,28.25,40.30,75.00]
''' 约束:
- 您必须使用收据价值的100%,我们不希望有剩余的钱
- 您可以订购任何数量的任何菜单项
- 所有收据值都不是“技巧”,它们都有答案
找到加起来就是收据总数的第一个食物组合,只打印出该收据的一个组合,然后转到下一个收据。
输出格式取决于您,但是下面是一些示例:
4.85: 3种食物,额外的蔬菜,薯条,奶酪
13.75: 3个项目,{'素食三明治':1,'玉米片':2}
示例: 4.85收据具有三种可能的组合:
- 最佳:玉米片,薯条(共2件)
- 额外的蔬菜,薯条,奶酪(总共3次)
- 薯片,薯片,汽水(共3件) '''
现在有两种解决方案。
- 对字典进行排序
- 直接递归剩余金额。
- 这里的问题是,一次递归传递还不够好(如果我们需要多个相同的条目),即我将字典中的第一个条目取走,然后尝试递归地找到下一个适合收据的条目,如果还有剩余,递归地找到适合剩余量的元素。
- 在上面的递归调用中,我将第一个项固定到第二级,然后将剩余金额检查为
- 我也必须在第一级上完成4)。
class Solution:
def getItems(self,orev: dict,remain: int) :
rev = collections.OrderedDict(sorted(orev.items()))
list = []
for i in rev:
list = self.getMine(rev,round(remain-i,2))
if list != [-1]:
list.append(rev[i])
return list
return list
def getMine(self,rev: dict,remain: int):
list = []
if remain < 0:
retlist = [-1]
return retlist
if remain in rev:
list.append(rev[remain])
return list
for i in rev:
retlist = self.getMine(rev,2))
if retlist != [-1]:
list.extend(retlist)
list.append(rev[i])
return list
return [-1]
第二种方法是使用BST,但与上述方法相同
我觉得这意味着我们正在做n ^ n。
我不知道如何优化它。
解决方法
您在正确的轨道上。您知道还剩多少美元以及您在哪个项目上的递归是一个很好的起点,但是,不只是通过获取或离开当前项目进行递归,还应先递减0,然后取1,然后取2,等等等等。如果在任何时候还剩$ 0,请打印出当前有多少项并返回True
,但是如果到达最后一项仍不能使它工作,请返回False
。时间的复杂性将是模糊的,但肯定可以。
您可以使用称为“动态编程”的技术来提高性能。您会做的是,请注意,在任何时候,如果您正在查看商品5
,而您还有$5.63
,那么您就不在乎如何 ,并且可以继续解决该问题,就好像以前的项目根本不存在一样。此外,如果您将答案保存为[项目5,金钱5.63],那么如果您以其他方式到达那里,则无需做任何其他工作,只需立即返回保存的答案即可。如果这样做,您的时间复杂度将为O(n*m)
,其中n
是项目数,m
是不同的允许货币可能性的总数(在这种情况下,是输入货币,以美分计)。这种方法的实现更加深入,但是您可以通过Google 动态编程更好地了解这里发生的事情。
这是我在interviewing.io上最喜欢的模拟面试问题之一,我在那里向OP提出了这个挑战。
您可以使用 DFS、BFS、DP 或蛮力解决它,但回溯组件对于正确解决至关重要。进行递归会产生更少的代码,并且记忆会加快它的速度,但是如果你采用自下而上的方法(从 $0 开始并计算到收据值),记忆会容易得多,而不是从收据值开始直到你到 0。
问题的第一部分是“找到任何答案”,问题的第二部分是“找到最小的项目列表”。在这一点上,您可以采用 Coin Change 的策略,在那里您采取贪婪的方法并首先花钱购买昂贵的东西。这并不总是立即为您提供最佳答案,但与按价格升序对菜单进行排序相比,您会更接近最小的答案。
通过查看最大深度原则,还有其他快捷方式可以适应如何更快地解决问题。例如,如果您的最佳答案是 10 个项目,为什么要建立一个完整的 20 个项目列表(这仍然使您自上而下达到 0 美元,或自下而上达到确切的收据金额)然后才意识到它不是“更好”的答案是更短的项目列表。
第二部分的常见入门级方法是收集“每个”答案并在结果列表中找到最小的答案,但在最近对该问题的改编中,您最终会得到数百万种组合和排列。但是,如果您有“额外的蔬菜、薯条、奶酪”的答案,您必须找到“奶酪、薯条、额外的蔬菜”的排列组合,才能确定最终是完全相同的列表。
如果我们在模拟面试后得到介绍,您应该可以访问我的电子邮件地址,我很乐意就此问题保持联系并讨论其他想法。或者更好的是,您可以要求 IIO 支持团队再次配对我们。 :)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。