标准的一点变化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,我们需要多地图,或类似的东西。
答案 0 :(得分:6)
从基本的O(2 ^ n)强力算法开始。
改进的算法,称为中间算法中的meet,将输入列表拆分为相等大小的一半。前半部分受基本蛮力算法的约束,其中生成所有子集,计算它们的总和,并将总和与目标进行比较。有可能但不太可能在上半年找到目标。如果不是,算法会生成后半部分的所有子集,并检查每个总和,以查看目标和总和之间的差异是否是前半部分的总和,在这种情况下,找到了所需的子集。
我在我的博客上发了implementation。