使用不同的二进制数来查找给定集的子集

时间:2015-10-26 01:52:46

标签: javascript java c# algorithm big-o

因此,面临的挑战是设计一种打印给定集合n的子集的算法。

让我们设置n:

 n = {a,b,c}

在这个stack overflow article上,@ Piva有一个答案可以解决这个问题,使用"每个0到2 ^ n的数字在其二进制表示中给出一个唯一的子集"

我写过@Piva代码的Javascript版本,效果很好。除了一行之外,我理解其中的大部分内容:

if(((i>>j) & 1) === 1)

我想我理解这行代码正在向右移位,在我的二进制表示的开头添加了j个零。我也明白了这一点。将i>> j与1进行比较并查看输出i>>中的第一位是否打开。

但我不明白此操作如何识别唯一的二进制表示以及为什么if(((i>>j) & 1) === 1)为真意味着我们拥有给定n的唯一子集。

这是我的Javascript版本:

    function SubsetBuilder(set) {
        this.set = set;

    }

    SubsetBuilder.prototype.getSubsets = function () {
        var self = this;

        if (!self.set)
            return null;

        //recursive way, do next
        var getSubsetsAll = function (originalSet) {
            if (!originalSet) {
                return;
            }
        }

        var n = this.set.length;
        for(var i = 0; i < (1<<n); i++) {
            var subset = [];
            for (var j = 0; j < n; j++) {
                console.log('i:' + i + ", binary: " + i.toString(2));
                console.log('j:' + j + ", binary: " + j.toString(2));
                console.log('(i >> j):');
                console.log((i >> j));
                console.log('((i>>j) & 1):');
                console.log(((i >> j) & 1));
                if(((i>>j) & 1) === 1){ // bit j is on
                    subset.push(this.set[j]);
                }
                console.log('-------------------');
            }
            console.log(subset);
            console.log('-------------------');
        }
    }

    var set = ['a', 'b', 'c'];
    var obj = new SubsetBuilder(set);
    obj.getSubsets();

1 个答案:

答案 0 :(得分:3)

if(((i>>j) & 1) === 1)检查i的第j位是否已设置。

要了解其工作原理,请考虑二进制101b中的数字5。 >>只是一个转变(或等效地,除以2 n ),& 1除了最低有效位之外的其他所有内容。

(101b >> 0) & 1 = (101b & 1) = 1
(101b >> 1) & 1 = ( 10b & 1) = 0
(101b >> 2) & 1 = (  1b & 1) = 1 

因此,一旦了解了位提取的工作原理,我们就需要理解为什么位提取等同于子集包含:

以下是我们如何将二进制数0-7映射到{A,B,C}的子集

0: 0 0 0   => {     }
1: 0 0 1   => {    A}
2: 0 1 0   => {  B  }
3: 0 1 1   => {  B A}
4: 1 0 0   => {C    }
5: 1 0 1   => {C   A}
6: 1 1 0   => {C B  }
7: 1 1 1   => {C B A}

显然我们列出了所有子集。

希望您现在可以看到为什么i的第j位测试等同于将第j个对象包含到第i个子集中。