我正在寻找一种算法,它可以采用两组整数(正数和负数),并找到每个具有相同总和的子集。
问题类似于subset sum problem,除了我正在寻找双方的子集。
以下是一个例子:
列出A {4,5,9,10,1}
列出B {21,7,-4,180}
所以这里唯一的匹配是: {10,1,4,9}< => {21,7,-4}
有谁知道这类问题是否存在现有算法?
到目前为止,我所拥有的唯一解决方案是蛮力方法,它尝试每个组合,但它在指数时间内执行,我不得不对要考虑的元素数量设置硬限制,以避免花费太长时间
我能想到的唯一其他解决方案是在两个列表上运行一个阶乘,并在那里查找等式,但这仍然不是很有效,并且随着列表变大而需要更长的时间。
答案 0 :(得分:9)
与子集求和问题一样,这个问题是弱 NP-complete,因此它有一个以时间多项式(M)运行的解,其中M是问题中出现的所有数字的总和实例。您可以通过动态编程实现这一目标。对于每个集合,您可以通过填充二维二进制表来生成所有可能的总和,其中(k,m)处的“真”表示可以通过从集合的前k个元素中挑选一些元素来实现子集和m。
你迭代地填充它 - 如果(k-1,m)设置为“true”,你将(k,m)设置为“true”(显然,如果你可以从k-1元素得到m,你可以得到它来自k个元素,不选择第k个)或if(k-1,md)被设置为“true”,其中d是集合中第k个元素的值(你选择第k个的情况)元件)。
填写表格可以获得最后一列(代表整个集合的那一列)中所有可能的总和。对两个集合执行此操作并查找公共总和。您可以通过反转用于填充表格的过程来回溯表示解决方案的实际子集。
答案 1 :(得分:9)
其他人所说的是真的:
这个问题是NP完全的。简单的减少是通常的子集和。只有当A联合(-B)的非空子集合为零时,您才能通过注意A的子集与B的子集(不是两者都是和)来证明这一点。
这个问题只是NP完全弱,因为它是数字大小的多项式,但在对数中推测它是指数的。这意味着问题比“NP-complete”可能暗示的绰号更容易。
您应该使用动态编程。
那么我对这次讨论的贡献是什么?好吧,代码(在Perl中):
@a = qw(4 5 9 10 1);
@b = qw(21 7 -4 180);
%a = sums( @a );
%b = sums( @b );
for $m ( keys %a ) {
next unless exists $b{$m};
next if $m == 0 and (@{$a{0}} == 0 or @{$b{0}} == 0);
print "sum(@{$a{$m}}) = sum(@{$b{$m}})\n";
}
sub sums {
my( @a ) = @_;
my( $a, %a, %b );
%a = ( 0 => [] );
while( @a ) {
%b = %a;
$a = shift @a;
for my $m ( keys %a ) {
$b{$m+$a} = [@{$a{$m}},$a];
}
%a = %b;
}
return %a;
}
打印
sum(4 5 9 10) = sum(21 7)
sum(4 9 10 1) = sum(21 7 -4)
所以,值得注意的是,有多个解决方案适用于您的原始问题!
编辑:用户itzy正确地指出此解决方案是错误的,更糟糕的是,在多种方式!我很抱歉,我希望在上面的新代码中解决这些问题。尽管如此,仍然存在一个问题,即对于任何特定的子集和,它只打印一种可能的解决方案。与之前出现的直接错误问题不同,我将其归类为故意限制。祝你好运并提防虫子!
答案 2 :(得分:1)
非常感谢所有快速反应!
动态编程解决方案与我们现在的详尽解决方案并没有什么不同,我想如果我们需要最优解决方案,我们需要考虑每个可能的组合,但生成这个详尽的总和列表所花费的时间也是如此长.. 快速测试以及为x个元素生成所有可能总和所需的时间超过1分钟:
11 elements took - 0.015625 seconds
12 elements took - 0.015625 seconds
13 elements took - 0.046875 seconds
14 elements took - 0.109375 seconds
15 elements took - 0.171875 seconds
16 elements took - 0.359375 seconds
17 elements took - 0.765625 seconds
18 elements took - 1.609375 seconds
19 elements took - 3.40625 seconds
20 elements took - 7.15625 seconds
21 elements took - 14.96875 seconds
22 elements took - 31.40625 seconds
23 elements took - 65.875 seconds
24 elements took - 135.953125 seconds
25 elements took - 282.015625 seconds
26 elements took - 586.140625 seconds
27 elements took - 1250.421875 seconds
28 elements took - 2552.53125 seconds
29 elements took - 5264.34375 seconds
对于我们试图解决的业务问题并不是真的可以接受。我将回到绘图板,看看我们是否确实需要了解所有解决方案,或者我们只能做一个(最小/最大的子集,例如)而且希望这可以帮助简化问题并使我的算法能够满足期望。
非常感谢!
答案 3 :(得分:0)
子集和是Np-complete,你可以多项式地减少你的问题,所以你的问题也是NP完全的。