input是int数组,获取所有子集

时间:2015-11-13 11:51:18

标签: java algorithm

我想获得可能的子集,例如:input是{1,2,3}

预期结果:

1
2
3
1,2
1,3
1,2,3
2,3

我使用递归来实现它,它认为它很慢,它有更有效的方法吗?

3 个答案:

答案 0 :(得分:1)

您可以考虑一种递归方法:

  1. 如果您只有一个号码,那么这是唯一可能的金额
  2. 如果您有多个号码,而不是每个号码: 将它与剩余数字的所有可能总和相结合的数字也是总和。
  3. PSEUDO CODE:

    allsums = makeAllSums(setOfNumbers){
      if(1==setOfNumbers.size)
        return setOfNumbers.head
      result = emptySet
      for(a in setOfNumbers)
        allSubSums=makeAllSums(setOfNumbers without a);
        for(b in allSubSums)
          result.add(a."+".b)
      return result 
    }
    

    你只需要考虑避免重复。

答案 1 :(得分:1)

这是subset sum problem的变体,可以使用Dynamic ProgrammingO(n*SUM)中解决,其中SUM是所有数字的总和。

D(i,x) = D(i-1,x) OR D(i-1,x-arr[i])
D(0,0) = true
D(0,x) = false    x != 0

在此处,D(i,x)给出一个布尔值,指示是否可以使用部分或全部x第一个元素来达到总和i。因此,对于每个可能的总和xD(n,x)表示是否可以使用任何数字达到此总和。

答案 2 :(得分:0)

基于要添加到总和的元素的二进制数表示的想法
从最初的集合。

1 2 3 4 5 6 7 9 10

每个可能的总和可以写成8位二进制数字,其中每个数字代表'取这个总和'不要把这个用在总和中。

示例:

001010100  means 3+5+7
111111111  means 1+2+3+4+5+6+7+9+10
000000001  means 10
010000000  means 2

因此,每个可能的总和可以写成长度为9的0和1的序列。

所有总和都是长度为9的可能序列。

所以你可以简单地循环数字1到2 ^ 9-1并将二进制表示解释为总和。

000000001   : 10
000000010   : 9
000000011   : 9 + 10
000000100   : 7
000000101   : 7 + 10
...
111111111   : 1+2+3+4+5+6+7+9+10

这样你就得到了所有的金额(没有重复)