给定一组n个整数,列出所有可能的子集,其中sum为> = k

时间:2013-08-06 16:33:12

标签: algorithm

给定数组形式的未排序整数集,找到所有可能的子集,其总和大于或等于const整数k, 例如: - 我们的集合是{1,2,3}和k = 2

可能的子集: -

 {2},
 {3},
 {1,2},
 {1,3},
 {2,3}, 
 {1,2,3}

我只能想到一个简单的算法,它列出了集合的所有子集,并检查子集的总和是否为> = k,但是它的指数算法并且列出所有子集需要O(2 ^ N)。我可以使用动态编程在多项式时间内解决它吗?

3 个答案:

答案 0 :(得分:10)

列出所有子集将仍然是O(2^N),因为在最坏的情况下,您可能仍需要列出除空子集之外的所有子集。

动态编程可以帮助您计算具有sum >= K

的集合数量

您可以自下而上跟踪从范围[1..K]总计到某个值的子集数。这样的方法将是O(N*K),这对于小K来说是可行的。

动态编程解决方案的想法最好用一个例子来说明。考虑这种情况。假设您知道在由第一个i元素组成的所有集合中,您知道t1总和为2t2总和为3。假设下一个i+1元素是4。给定所有现有集合,我们可以通过附加元素i+1或将其遗漏来构建所有新集合。如果我们将其删除,我们会得到t1个子集,这些子集总和为2t2个子集,总和为3。如果我们附加它,那么我们会获得总计为t1(2 + 4)和6的{​​{1}}子集,其总和为t2(3 + 4),并且包含一个子集只有7总和为4.这为我们提供了总和为i+1的子集数量,这些子集由第一个(2,3,4,6,7)元素组成。我们会一直持续到i+1

在伪代码中,这看起来像这样:

N

答案 1 :(得分:6)

  

我可以使用动态编程在多项式时间内解决它吗?

没有。问题甚至比@amit(在评论中)提到的更难。找出是否存在与特定k相加的子集是subset-sum problem,这是NP难的。相反,你要求有多少解决方案等于特定的k,这是更加困难的P#类。此外,您确切的问题稍微困难一些,因为您不仅要计算,而且要枚举k和目标的所有可能子集< ķ。

答案 2 :(得分:1)

如果k为0,并且该集合的每个元素都是正数,那么您别无选择,只能输出每个可能的子集,因此该问题的下限是O(2 N ) - - 产生输出所需的时间。

除非你知道更多关于你没有告诉我们的价值k的信息,否则没有更快的通用解决方案来检查每个子集。