2015-10-26 2 views
0

Таким образом, задача состоит в разработке алгоритма, который ПРИНЦИПЫ подмножеств заданного набора n.Использование различных двоичных чисел для поиска подмножеств заданного набора

Зададим п равна:

n = {a,b,c} 

На этой stack overflow article есть ответ от @Piva, который решает эту проблему, используя тот факт, что «Каждое число от 0 до 2^п дает уникальное подмножество в его двоичный представление "

Я написал Javascript версию кода @ Piva, она работает хорошо. Я понимаю, большинство из них, кроме одной строки:

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

Я думаю, что я понимаю, эта строка кода смещается I бит вправо, добавление J нулей в начале я в двоичном представлении. Я также понимаю, что бит & сравнивает i >> j с 1 и видит, включен ли первый бит с выхода i >>.

Но я не понимаю, как эта операция идентифицирует уникальные двоичные представления и почему истина означает, что у нас есть уникальное подмножество данного 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(); 
+0

Я добавил комментарий, чтобы ответить на ваш вопрос в ответ. Я не чувствую, что это требует совершенно нового вопроса. –

ответ

3

if(((i>>j) & 1) === 1) проверяет, является ли J-й бит I установлен.

Чтобы понять, как это работает, рассмотрите номер 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 => { 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} 

И, очевидно, мы перечислили все подмножества.

Надеюсь, теперь вы можете увидеть, почему тест для j-го бита i эквивалентен включению j-го объекта в i-ю подмножество.

+0

Хорошо, я добираюсь туда, я беспокоюсь, что это заставляет меня так долго, чтобы понять это, хотя я писал код почти 20 лет. Поэтому я получаю, что битовая маска - это способ «пометить» подмножества множества n. Я вижу теперь, благодаря вашему ответу, что if ((i >> j) & 1) === 1) проверяет, является ли j-й бит i «включенным», а i - это битовая маска, которая отмечает точку , с бинарным 1, где мы имеем единственное подмножество. Несколько вещей, которые я хотел бы уточнить, оператор >> в частности. Я понимаю, что делает 1 << n, и я могу представить двоичную нотацию и сдвиг этого, но у меня возникают проблемы с i >> j –

+0

. Я бы прочитал i >> j следующим образом: «добавьте j нулей в начало бинарного обозначения i "? –

+0

Прояснил, что делает каждый из операторов в описании. –

Смежные вопросы