O(2 ^(k / 2))时间内K元素的子集和

时间:2013-12-03 16:55:48

标签: c++ performance algorithm implementation

标准的一点变化Subset Sum Problem是我们想要从一组N大小中找到K大小的子集,其总和达到S.

标准蛮力解决方案产生复杂度O(N ^ K)。但是,上面的链接提到了一种蛮力方法的变化,复杂度为O(N ^(K / 2))。

维基文章说

  

已知一种更好的指数时间算法,该算法及时运行   O(2N / 2)。该算法任意地将N个元素分成两组   每个N / 2。对于这两组中的每一组,它存储一个总和列表   其元素的所有2N / 2个可能子集。这两个列表中的每一个   然后排序。为此使用标准比较排序算法   步骤需要时间O(2N / 2N)。但是,给出一个排序的总和列表   对于k个元素,列表可以扩展为两个排序列表   引入一个(k + 1)st元素,这两个排序列表即可   在时间O(2k)合并。因此,每个列表可以以排序的形式生成   在时间O(2N / 2)。给定两个排序列表,算法可以检查   if第一个数组的元素和第二个数组的元素   总结到时间O(2N / 2)。为此,算法通过   第一个数组按降序排列(从最大元素开始)   和第二个数组按递增顺序(从最小的开始   元件)。每当第一个数组中当前元素的总和   并且第二个数组中的当前元素大于s   算法移动到第一个数组中的下一个元素。如果它少了   比s,算法移动到第二个数组中的下一个元素。   如果找到两个带有sum的元素,它就会停止。

现在基本上它说如果我们想要找到大小为k的子集,我们计算n个散列大小为K / 2的所有子集及其SUM,其中sum是散列中的关键。然后检查是否有两组大小(k / 2)总和为S。

我理解算法,但无法弄清楚,我们怎样才能实现它。 散列整数(Sum),其值为列表元组,其中包含实际集合的(K / 2)索引。

我们如何在C ++中有效地实现它。使用Data sturctures? 由于大小(k / 2)元素的和,可以并且将是非唯一的,我们不能使用MAP,我们需要多地图,或类似的东西。

1 个答案:

答案 0 :(得分:6)

从基本的O(2 ^ n)强力算法开始。

改进的算法,称为中间算法中的meet,将输入列表拆分为相等大小的一半。前半部分受基本蛮力算法的约束,其中生成所有子集,计算它们的总和,并将总和与目标进行比较。有可能但不太可能在上半年找到目标。如果不是,算法会生成后半部分的所有子集,并检查每个总和,以查看目标和总和之间的差异是否是前半部分的总和,在这种情况下,找到了所需的子集。

我在我的博客上发了implementation