因此所面临的挑战是设计一个算法,打印一组给定的子集 N
。
让我们设置N个相等的:
N = {A,B,C}
在此stack溢出文章有来自@Piva,解决了使用从0到2的n次方每一个数字给出了二进制重新presentation唯一子集
其实这个问题的答案我已经写了一个JavaScript版本@皮瓦的code,效果很好。据我所知大部分只是一条线:
如果(((I>> j)条和放大器; 1)=== 1)
我想我明白这行code正在改变i位右,下J零到我的二重presentation开始。我也明白了一点聪明和放大器;在比较I >> j送至1,看到如果第一位是从输出I >>。
不过,我不明白这是如何操作识别唯一的二进制重新presentations,为什么如果(((I>> j)条和放大器; 1)=== 1)
是真正的意味着我们有一个独特的子集一个给定的 N
。
下面是我的Javascript版本:
函数SubsetBuilder(套){
this.set =设置;
}
SubsetBuilder.prototype.getSubsets =功能(){
无功自我=这一点;
如果(!self.set)
返回null;
//递归的方式,下一步
VAR getSubsetsAll =功能(originalSet){
如果(!originalSet){
返回;
}
}
变种N = this.set.length;
为(变种I = 0; I&≤(1&所述; n种);我++){
变种子集= [];
为(变种J = 0; J&n种; J ++){
的console.log('I:'+ I +,二进制:+ i.toString(2));
的console.log('J:+ J +,二进制:+ j.toString(2));
的console.log('(I>> j)条:);
的console.log((I>> j)条);
的console.log('((ⅰ>> j)条和安培; 1):);
的console.log(((ⅰ>> j)条和安培; 1));
如果(((ⅰ>> j)条和安培; 1)=== 1){// j位是上
subset.push(this.set [J]);
}
的console.log('-------------------');
}
执行console.log(集);
的console.log('-------------------');
}
}
VAR集= ['A','B','C'];
VAR OBJ =新SubsetBuilder(套);
obj.getSubsets();
解决方案
如果(((I>> j)条和放大器; 1)=== 1)
检查如果i的第j个位被设置
要理解这是如何工作的,考虑5号二进制101B。
>>
只是一个转移(或者,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 => { 一个}
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子集
So the challenge is to design an algorithm that PRINTS the subsets of a given set n
.
Let's set n equal:
n = {a,b,c}
On this stack overflow article there is an answer from @Piva that solves this problem using the fact that "Each number from 0 to 2^n gives a unique subset in its binary representation"
I have written a Javascript version of @Piva's code, it works well. I understand most of it except one line:
if(((i>>j) & 1) === 1)
I think I understand this line of code is shifting i bits right, adding j zeros to the beginning of i's binary representation. I also understand the bit wise & is comparing i >>j to 1 and seeing if the first bit is on from the output i >>.
But I don't understand how this operation identifies unique binary representations and why the if(((i>>j) & 1) === 1)
being true means we have a unique subset of a given n
.
Here is my Javascript version:
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();
解决方案
if(((i>>j) & 1) === 1)
checks if the j-th bit of i is set.
To understand how this works, consider the number 5 in binary 101b.
>>
is just a shift (or equivalently, division by 2n) and & 1
masks out all but the least significant bit.
(101b >> 0) & 1 = (101b & 1) = 1
(101b >> 1) & 1 = ( 10b & 1) = 0
(101b >> 2) & 1 = ( 1b & 1) = 1
So once wen understand how the bit-extraction works, we need to understand why bit-extraction is equivalent to subset inclusion:
Here's how we map from binary numbers 0-7 to subsets of {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}
And clearly we have listed all subsets.
Hopefully you can now see why the test for the j-th bit of i is equivalent to the inclusion of the j-th object into the ith subset.