Algorithm 给定一组20个不同的正整数,找出两个和相同的子集

Algorithm 给定一组20个不同的正整数,找出两个和相同的子集,algorithm,partition-problem,Algorithm,Partition Problem,例如,如果A={10,20,30,40,…,200},那么{10,20,30,40,100}和{90,110}是具有相同总和(即200)的两个子集 因为输入的长度只有20?难道我们不能简单地生成所有的数字组合,计算它们的和并将它们存储在哈希映射[key=sum,value=count]中,然后在映射项上进行迭代,以查看该和是否被多次计算 经过一点实验,我确信简单地计算所有的2^n和并存储它们是最好的方法。然而,实现一个小集合的效率对于避免计算O(2^n*n)和花费太长时间至关重要 我使用了0到2

例如,如果A={10,20,30,40,…,200},那么{10,20,30,40,100}和{90,110}是具有相同总和(即200)的两个子集


因为输入的长度只有20?难道我们不能简单地生成所有的数字组合,计算它们的和并将它们存储在哈希映射[key=sum,value=count]中,然后在映射项上进行迭代,以查看该和是否被多次计算

经过一点实验,我确信简单地计算所有的2^n和并存储它们是最好的方法。然而,实现一个小集合的效率对于避免计算O(2^n*n)和花费太长时间至关重要

我使用了0到2^n-1的整数来表示所有子集(powerset)的集合

所有等和子集的计算很简单:

public void buildLists(){
    int maxlen = 0;
    int maxsum = 0;
    for( int i = 0; i <= max; i++ ){
       int s = sum( i );
        List<Integer> set = sum2sets.get( s );
        if( set == null ){
        set = new ArrayList<Integer>();
            sum2sets.put( s, set );
        }
        set.add( i );
        int len = sum2sets.size();
        if( len > maxlen ){
            maxsum = s;
            maxlen = len;
        }
    }
    System.out.println( "max. len " + maxlen + " at " + maxsum );
}
以及辉煌的成果(只是一小部分):


由于您正在寻找具有相同总和的两个子集-我看不到计算所有可能子集的方法[即
O(2^n)
],并且正如您所建议的那样-将它们存储在HashMap(key=sum和val=subset)中。
10+20+40==30+40
是有效的答案吗?这两个子集必须完全不同,而不仅仅是不相同的子集?我假设是的,但是问题应该被编辑以澄清。@alfasin,如果集合中正好有一个奇数,而所有其他的都是偶数,那么很明显,奇数不能用于任何一个子集中。因此,它可以被完全移除。这是一个可以应用的逻辑示例,这意味着我们不必简单地对每个子集求和。@AaronMcDaid“因为输入的长度只有20…”如果输入“只有20”或“大得多”删除一个数字是没有意义的…@我希望能够有效地找到一对不相交的等和集,但这并没有实现。所以我收回了我的第一个答案(即使从一个不相交的对中得出一系列对而不必计算它们的和是有效的)不是答案:这个问题是针对所有子集提出的,这个答案涉及对only@alfasin显然,我必须用相同的和计算所有子集,才能找到对的数目。但如果你看一下标题,你会清楚地看到“两个子集”,我把它理解为(可能是错误的)对所有可能的两个子集的要求。这真的是你投反对票的原因吗?@alfasin阅读我的答案:上面写着“例如,对于sum 105,有15272个集合”。是的,代码也只是一个例子,最后两行也是如此,但所有这些例子都涉及2大小的子集。@alfasin哪里是“所有这些例子都涉及2大小的子集”?我研究了所有的子集,对于两个有20个整数的集合。
private int sum( int n ){
    int s = 0;
    for( int i = 0; n > 0; i++ ){
        if( (n & 1) != 0 ) s += theSet[i];
        n = n >> 1;
    }
    return s;
}
public void buildLists(){
    int maxlen = 0;
    int maxsum = 0;
    for( int i = 0; i <= max; i++ ){
       int s = sum( i );
        List<Integer> set = sum2sets.get( s );
        if( set == null ){
        set = new ArrayList<Integer>();
            sum2sets.put( s, set );
        }
        set.add( i );
        int len = sum2sets.size();
        if( len > maxlen ){
            maxsum = s;
            maxlen = len;
        }
    }
    System.out.println( "max. len " + maxlen + " at " + maxsum );
}
public String setAsString( int n ){
    StringBuilder sb = new StringBuilder( "[" );
    String del = "";
    for( int i = 0; n > 0; i++ ){
        if( (n & 1) != 0 ){
            sb.append( del ).append( theSet[i] );
            del = ", ";
        }
        n = n >> 1;
    }
    sb.append( "]" );
    return sb.toString();
}

public void dumpAll( int n ){
    for( Map.Entry<Integer,List<Integer>> e: sum2sets.entrySet() ){
        int sum = e.getKey();
        List<Integer> sets = e.getValue();
        if( sets.size() >= 2 ){
            System.out.println( "sum: " + sum );
            for( Integer i: sets ){
                System.out.print( " " + setAsString( i ) );
            }
            System.out.println();
            if( --n == 0 ) break;
        }
    }
}
public static void main( String[] args ){
    int[] nums = new int[]{
         3,   7, 13, 18, 21, 22, 30, 34, 42, 49,
         50, 61, 65, 67, 70, 71, 88, 91, 93, 99 };
    Sum sum = new Sum( nums );
    sum.buildLists();
    sum.dumpAll( 50 );
}
max. len 963 at 994
sum: 21
  [3, 18] [21]
sum: 25
  [7, 18] [3, 22]
sum: 28
  [3, 7, 18] [7, 21]
sum: 31
  [13, 18] [3, 7, 21]
sum: 34
  [3, 13, 18] [13, 21] [34]
sum: 37
  [3, 13, 21] [7, 30] [3, 34]
sum: 38
  [7, 13, 18] [3, 13, 22]
sum: 40
  [18, 22] [3, 7, 30]
sum: 41
  [3, 7, 13, 18] [7, 13, 21] [7, 34]
sum: 42
  [3, 18, 21] [7, 13, 22] [42]
sum: 43
  [3, 18, 22] [21, 22] [13, 30]
sum: 44
  [3, 7, 13, 21] [3, 7, 34]
sum: 45
  [3, 7, 13, 22] [3, 42]
sum: 46
  [7, 18, 21] [3, 21, 22] [3, 13, 30]
sum: 47
  [7, 18, 22] [13, 34]
sum: 49
  [3, 7, 18, 21] [7, 42] [49]
sum: 50
  [3, 7, 18, 22] [7, 21, 22] [7, 13, 30] [3, 13, 34] [50]
sum: 51
  [3, 18, 30] [21, 30]
sum: 52
  [13, 18, 21] [22, 30] [18, 34] [3, 7, 42] [3, 49]
sum: 53
  [13, 18, 22] [3, 7, 21, 22] [3, 7, 13, 30] [3, 50]
sum: 54
  [3, 21, 30] [7, 13, 34]
sum: 55
  [3, 13, 18, 21] [7, 18, 30] [3, 22, 30] [3, 18, 34] [21, 34] [13, 42]
sum: 56
  [3, 13, 18, 22] [13, 21, 22] [22, 34] [7, 49]
sum: 57
  [3, 7, 13, 34] [7, 50]
sum: 58
  [3, 7, 18, 30] [7, 21, 30] [3, 21, 34] [3, 13, 42]
sum: 59
  [7, 13, 18, 21] [3, 13, 21, 22] [7, 22, 30] [7, 18, 34] [3, 22, 34] [3, 7, 49]
sum: 60
  [7, 13, 18, 22] [18, 42] [3, 7, 50]
sum: 61
  [18, 21, 22] [13, 18, 30] [3, 7, 21, 30] [61]
sum: 62
  [3, 7, 13, 18, 21] [3, 7, 22, 30] [3, 7, 18, 34] [7, 21, 34] [7, 13, 42] [13, 49]
sum: 63
  [3, 7, 13, 18, 22] [7, 13, 21, 22] [7, 22, 34] [3, 18, 42] [21, 42] [13, 50]
sum: 64
  [3, 18, 21, 22] [3, 13, 18, 30] [13, 21, 30] [30, 34] [22, 42] [3, 61]
sum: 65
  [13, 22, 30] [13, 18, 34] [3, 7, 21, 34] [3, 7, 13, 42] [3, 13, 49] [65]
sum: 66
  [3, 7, 13, 21, 22] [3, 7, 22, 34] [3, 21, 42] [3, 13, 50]
sum: 67
  [3, 13, 21, 30] [3, 30, 34] [7, 18, 42] [3, 22, 42] [18, 49] [67]
sum: 68
  [7, 18, 21, 22] [7, 13, 18, 30] [3, 13, 22, 30] [3, 13, 18, 34] [13, 21, 34] [18, 50] [7, 61] [3, 65]
sum: 69
  [18, 21, 30] [13, 22, 34] [7, 13, 49]
sum: 70
  [18, 22, 30] [3, 7, 18, 42] [7, 21, 42] [3, 18, 49] [21, 49] [7, 13, 50] [3, 67] [70]
sum: 71
  [3, 7, 18, 21, 22] [3, 7, 13, 18, 30] [7, 13, 21, 30] [3, 13, 21, 34] [7, 30, 34] [7, 22, 42] [22, 49] [3, 18, 50] [21, 50] [3, 7, 61] [71]
sum: 72
  [3, 18, 21, 30] [7, 13, 22, 30] [7, 13, 18, 34] [3, 13, 22, 34] [30, 42] [3, 7, 13, 49] [22, 50] [7, 65]
sum: 73
  [3, 18, 22, 30] [21, 22, 30] [18, 21, 34] [13, 18, 42] [3, 7, 21, 42] [3, 21, 49] [3, 7, 13, 50] [3, 70]
sum: 74
  [13, 18, 21, 22] [3, 7, 13, 21, 30] [18, 22, 34] [3, 7, 30, 34] [3, 7, 22, 42] [7, 18, 49] [3, 22, 49] [3, 21, 50] [13, 61] [7, 67] [3, 71]
sum: 75
  [3, 7, 13, 22, 30] [3, 7, 13, 18, 34] [7, 13, 21, 34] [3, 30, 42] [7, 18, 50] [3, 22, 50] [3, 7, 65]
sum: 76
  [7, 18, 21, 30] [3, 21, 22, 30] [3, 18, 21, 34] [7, 13, 22, 34] [3, 13, 18, 42] [13, 21, 42] [34, 42]
sum: 77
  [3, 13, 18, 21, 22] [7, 18, 22, 30] [3, 18, 22, 34] [21, 22, 34] [13, 30, 34] [13, 22, 42] [3, 7, 18, 49] [7, 21, 49] [3, 13, 61] [3, 7, 67] [7, 70]
sum: 78
  [3, 7, 13, 21, 34] [7, 22, 49] [3, 7, 18, 50] [7, 21, 50] [13, 65] [7, 71]
sum: 79
  [3, 7, 18, 21, 30] [3, 7, 13, 22, 34] [3, 13, 21, 42] [7, 30, 42] [3, 34, 42] [30, 49] [7, 22, 50] [18, 61]
sum: 80
  [3, 7, 18, 22, 30] [7, 21, 22, 30] [7, 18, 21, 34] [3, 21, 22, 34] [3, 13, 30, 34] [7, 13, 18, 42] [3, 13, 22, 42] [13, 18, 49] [3, 7, 21, 49] [30, 50] [13, 67] [3, 7, 70]
sum: 81
  [7, 13, 18, 21, 22] [7, 18, 22, 34] [18, 21, 42] [3, 7, 22, 49] [13, 18, 50] [3, 7, 21, 50] [7, 13, 61] [3, 13, 65] [3, 7, 71]
sum: 82
  [13, 18, 21, 30] [18, 30, 34] [18, 22, 42] [3, 7, 30, 42] [3, 30, 49] [3, 7, 22, 50] [3, 18, 61] [21, 61]
sum: 83
  [13, 18, 22, 30] [3, 7, 21, 22, 30] [3, 7, 18, 21, 34] [3, 7, 13, 18, 42] [7, 13, 21, 42] [7, 34, 42] [3, 13, 18, 49] [13, 21, 49] [34, 49] [3, 30, 50] [22, 61] [18, 65] [3, 13, 67] [13, 70]