查找大小为 n 的列表中的哪些数字与另一个数字相加的算法
我有一个十进制数(我们称之为目标)和一个其他十进制数数组(我们称之为数组元素),我需要找到以下数字的所有组合总和为目标的要素。
我更喜欢 C# (.Net 2.0) 中的解决方案,但无论如何,最好的算法可能会获胜。
您的方法签名可能类似于:
public decimal[][] Solve(decimal goal, decimal[] elements)
I have a decimal number (let's call it goal) and an array of other decimal numbers (let's call the array elements) and I need to find all the combinations of numbers from elements which sum to goal.
I have a preference for a solution in C# (.Net 2.0) but may the best algorithm win irrespective.
Your method signature might look something like:
public decimal[][] Solve(decimal goal, decimal[] elements)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
虽然没有解决暴力问题(正如其他人已经提到的),但您可能想首先对数字进行排序,然后检查剩下的可能的数字(因为一旦您传递了 Sum 值,您就不能添加任何大于 Goal 的数字 -和)。
这将改变您实现算法的方式(以便仅排序一次,然后跳过标记的元素),但平均而言会提高性能。
While not solving the problem of brute force (as others already mentioned) you might want to sort your numbers first, and then go over the possible ones left (since once you passed Sum value, you can't add any number larger than Goal - Sum).
This will change the way you implement your algorithm (in order to sort only once and then skip marked elements), but on the average would improve performance.
您描述了一个背包问题,唯一真正的解决方案是暴力破解。 有一些更快的近似解决方案,但它们可能无法满足您的需求。
You have described a knapsack problem, the only true solution is brute force. There are some approximation solutions which are faster, but they might not fit your needs.
我认为您遇到了装箱问题(这是NP难题) ,所以我认为唯一的解决方案是尝试每一种可能的组合,直到找到有效的组合。
编辑:正如评论中所指出的,您不会总是必须尝试每遇到的每组数字的组合。 然而,您想出的任何方法都有最坏情况的数字集,您将必须尝试每种组合 - 或者至少是增长的组合的子集与集合的大小呈指数关系。
否则,它就不是NP困难的了。
I think you've got a bin packing problem on your hands (which is NP-hard), so I think the only solution is going to be to try every possible combination until you find one that works.
Edit: As pointed out in a comment, you won't always have to try every combination for every set of numbers you come across. However, any method you come up with has worst-case-scenario sets of numbers where you will have to try every combination -- or at least a subset of combinations that grows exponentially with the size of the set.
Otherwise, it wouldn't be NP-hard.
子集和问题以及稍微更一般的背包问题可以通过动态规划来解决:不需要对所有组合进行强力枚举。 请查阅维基百科或您最喜欢的算法参考。
虽然这些问题是 NP 完全问题,但它们是非常“简单”的 NP 完全问题。 元素数量的算法复杂度较低。
The subset-sum problem, and the slightly more general knapsack problem, are solved with dynamic programming: brute-force enumeration of all combinations is not required. Consult Wikipedia or your favourite algorithms reference.
Although the problems are NP-complete, they are very "easy" NP-complete. The algorithmic complexity in the number of elements is low.
有趣的答案。 感谢您对维基百科的指点——虽然很有趣——但它们实际上并没有解决我在寻找精确匹配时所说的问题——更多的是会计/账簿平衡问题,而不是传统的装箱/背包问题。
我一直饶有兴趣地关注堆栈溢出的发展,并想知道它会有多大用处。 这个问题在工作中出现,我想知道堆栈溢出是否可以比我自己编写更快地提供现成的答案(或更好的答案)。 也感谢建议将此标记为家庭作业的评论 - 我想鉴于上述情况,这是相当准确的。
对于那些感兴趣的人,这是我的解决方案,它使用递归(自然)我也改变了对方法签名的想法并选择了 List>; 而不是十进制[][]作为返回类型:
如果您想要一个应用程序来测试它的工作原理,请尝试这个控制台应用程序代码:
我希望这可以帮助其他人更快地获得答案(无论是家庭作业还是其他)。
干杯...
Interesting answers. Thank you for the pointers to Wikipedia - whilst interesting - they don't actually solve the problem as stated as I was looking for exact matches - more of an accounting/book balancing problem than a traditional bin-packing / knapsack problem.
I have been following the development of stack overflow with interest and wondered how useful it would be. This problem came up at work and I wondered whether stack overflow could provide a ready-made answer (or a better answer) quicker than I could write it myself. Thanks also for the comments suggesting this be tagged homework - I guess that is reasonably accurate in light of the above.
For those who are interested, here is my solution which uses recursion (naturally) I also changed my mind about the method signature and went for List> rather than decimal[][] as the return type:
If you want an app to test this works, try this console app code:
I hope this helps someone else get their answer more quickly (whether for homework or otherwise).
Cheers...