在Java中计算数组所有子集的Bitwise和的有效方法是什么?

时间:2018-04-20 13:16:09

标签: java algorithm data-structures bit-manipulation

对于[1,2,3],所有可能的子集都是{1},{2},{3},{1,2},{1,3},{2,3},{1,2 ,3}

这些子集的AND之和为,1 + 2 + 3 + 0 + 1 + 2 + 0 = 9.

这就是我的尝试:

public class Main
{
static void printSubsets(int set[])
{
    int n = set.length;
    int total=0;

    for (int i = 0; i < (1<<n); i++)
    {
        int sum=1;

        for (int j = 0; j < n; j++)

            if ((i & (1 << j)) > 0)

                sum = sum & set[j];

                total= total+sum;


    }
    System.out.print(total);
}

public static void main(String[] args)
{
    int set[] = {1, 2, 3};
    printSubsets(set);
}
}

但它没有给出正确的输出

1 个答案:

答案 0 :(得分:2)

您可以总结每一位的贡献。

让我们从最低位开始。为了消除其他位的贡献,我们计算集合中所有数字的数字和位。对于您的示例,结果将是[1,0,1]。包含0的任何子集都不会给出任何贡献。所有仅由1组成的非空子集将给出1个贡献。总共将有2 ^ n - 1个这样的子集,每个子​​集贡献1。另一位也是如此。我们得到[0,2,2],每个子集给出2个。总共3 * 1 + 3 * 2 = 9

static void printSubsets(int[] set) {

    long total = 0;

    for (int bit=1; bit!=0; bit<<=1) {

        int numbersWithBitSet = 0;
        for (int i : set) {
            if ((i&bit)!=0) numbersWithBitSet++;
        }

        long subsets = (1L<<numbersWithBitSet)-1;
        total += bit * subsets;
    }

    System.out.println("Result: " + total);
}