我有一个数字列表,我有一个总和值。例如,
list = [1, 2, 3, 5, 7, 11, 10, 23, 24, 54, 79 ]
sum = 20
我想生成从该列表中取得的一系列数字,以便序列汇总到该目标。为了帮助实现这一目标,序列可以是任意长度,并且允许重复。
result = [2, 3, 5, 10]
,或result = [1, 1, 2, 3, 3, 5, 5]
或result = [10, 10]
我一直在对此问题进行大量研究,并发现 subset sum 问题值得关注。我的问题在某种程度上类似于子集求和问题,因为我想找到一个产生目标和的数字子集。
然而,与子集求和问题不同,它找到所有总和达到目标的数字集合(因此如果暴力强制则以指数时间运行),我只想找到一个一组数字。我想找到给我总和的第一套。所以,从某种意义上说,速度是一个因素。
此外,我希望算法有一定程度的随机性(或伪随机性)。也就是说,如果我使用相同的列表和多次运行算法,我应该每次都得到一组不同的数字。
实现这一目标的最佳算法是什么?
附加说明: 到目前为止我所取得的成就是使用了一种天真的方法,我循环遍历列表,将其添加到每个值的组合中。这显然需要很长时间,而且我现在对此并不感到太高兴。我希望有更好的方法来做到这一点!
如果没有给出精确总和的序列,我对一个序列感到满意,该序列给出的总和尽可能接近目标总和。
答案 0 :(得分:1)
正如其他人所说,这是一个NP问题 但是,这并不意味着小的改进是不可能的:
列表中有1吗? cmd.exe
是解决方案。排序列表中的O(1)
删除大于目标总和的列表元素。 O(n)
是否有[1,1,1,1...]
的列表元素x?再次,简单的解决方案O(n)
是否有(x%sum)==0
的列表元素x,y?删除x。为O(n ^ 2)
(可能是:是否有任何列表元素x,y,z与(x%y)==0
或(x%y)==z
?删除x.O(n ^ 3))
在使用完整递归之前,请尝试获取总和 只有最小的偶数和最小的奇数。
...
答案 1 :(得分:0)
子集和问题不是找到所有子集,而是确定是否存在某个子集。这是一个decision problem。 NP中的所有问题都是这样的。甚至这个更简单的问题是NP-complete。
这意味着如果你想要一个确切的答案(子集必须总和一些值),你将无法比任何子集和算法做得更好(除非P=NP,否则它是指数的)
答案 2 :(得分:0)
我会尝试将问题减少为对较小集合的强力搜索。
list
最小值排序为最大值。sum
和result
列表。重复{
list
小于target - sum
sum
,将绘制值添加到result
列表。}直到list[0] > sum
或sum == 0
sum != 0
,请强制搜索list
中与sum
和result
的小组合之间的差异相匹配的小组合。这种方法可能无法找到有效的解决方案,即使它们存在。然而,它可以快速找到解决方案或快速失败,然后再使用更深的整个集合来采用更慢的蛮力方法。
答案 3 :(得分:0)
这是解决问题的贪婪方法:
没有'随机性':
获取集合中小于所需总和的单个最大数字 - 我们将其命名为 X 。鉴于它是有序的,如果总和为2,最好是 O(1)和 O(N)。
因为你可以重复这个值 - 比如 c 次,所以要多次这样做,直到你最接近总和,但要小心!创建一系列值 - 基本上现在你将找到另一笔钱!您现在可以找到加起来 R =(sum - X * c )的数字。因此,找到小于 R 的最大数字。检查 R - (您刚刚找到的数字)= 0或者是否[ R - (您刚刚找到的数字)]%(较小的#s)== 0。 / p>
如果它变为 R > 0,使较小数字的部分和小于 R (由于该算法的性质,这将不会超过5~10次计算)。看看这些是否能满足它。
如果该步骤使 R < 0,删除一个 X 并再次启动该过程。
'随机':
随机获取 X ! : - )
注意:如果您有一些单个数字,这将最有效。