Как сгенерировать набор мощности заданного набора?

Я готовлюсь к собеседованию и наткнулся на этот вопрос в Интернете в категории «Математика».

Сгенерировать набор мощности данного набора:

int A[] = {1,2,3,4,5};  
int N = 5; 
int Total = 1 << N;
for ( int i = 0; i < Total; i++ ) { 
 for ( int j = 0; j < N; j++) {
  if ( (i >> j) & 1 ) 
      cout << A[j]; 
   } 
 cout <<endl;

 }

Пожалуйста, я не хочу явного ответа. Я просто хочу разъяснений и подсказок о том, как подойти к этой проблеме.

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

Кроме того, может ли кто-нибудь повторить, о чем идет речь.

Спасибо.


person Ralph    schedule 23.06.2014    source источник
comment
Набор мощности набора = {a,b} - это набор, состоящий из всех возможных комбинаций представляющих элементов набора, взятых по одному или ни одного одновременно. Здесь P(s)={{a},{b},{ab},{}};   -  person Am_I_Helpful    schedule 23.06.2014
comment
Очень интересует рекурсивный алгоритм для этой задачи!   -  person SMBiggs    schedule 12.02.2017
comment
Проверьте этот ответ: stackoverflow.com/a/19891145/1740808   -  person SergeyS    schedule 31.08.2018


Ответы (8)


Power set of a set A is the set of all of the subsets of A.

Не самое дружелюбное определение в мире, но пример поможет:

Например. для {1, 2} подмножества: {}, {1}, {2}, {1, 2}

Таким образом, набор мощности равен {{}, {1}, {2}, {1, 2}}


Чтобы сгенерировать набор мощности, посмотрите, как вы создаете подмножество: вы переходите к каждому элементу один за другим, а затем либо сохраняете его, либо игнорируете.

Пусть это решение будет обозначено битом (1/0).

Таким образом, чтобы сгенерировать {1}, вы возьмете 1 и бросите 2 (10).

В аналогичных строках вы можете написать битовый вектор для всех подмножеств:

  • {} -> 00
    {1} -> 10
    {2} -> 01
    {1,2} -> 11

Повторюсь: подмножество, если оно сформировано путем включения некоторых или всех элементов исходного множества. Таким образом, чтобы создать подмножество, вы переходите к каждому элементу, а затем решаете, сохранить его или отбросить. Это означает, что для каждого элемента у вас есть 2 решения. Таким образом, для набора вы можете получить 2^N различных решений, соответствующих 2^N различным подмножествам.

Посмотрим, сможешь ли ты забрать его отсюда.

person axiom    schedule 23.06.2014

Создайте набор мощности: {"A", "B", "C"}.


Псевдокод:

val set = {"A", "B", "C"}

val sets = {}

for item in set:
  for set in sets:
    sets.add(set + item)
  sets.add({item})
sets.add({})

Объяснение алгоритма:

1) Инициализировать sets пустым набором: {}.

2) Перебрать каждый элемент в {"A", "B", "C"}

3) Переберите каждый set в вашем sets.

3.1) Создайте новый набор, который является копией set.

3.2) Добавьте item к new set.

3.3) Добавьте new set к sets.

4) Добавьте item к вашему sets.

4) Итерация завершена. Добавьте пустой набор в свой resultSets.


Пошаговое руководство:

Давайте посмотрим на содержимое sets после каждой итерации:

Итерация 1, элемент = "А":

sets = {{"A"}}

Итерация 2, элемент = "B":

sets = {{"A"}, {"A", "B"}, {"B"}}

Итерация 3, элемент = "C":

sets = {{"A"}, {"A", "B"}, {"B"}, {"A", "C"}, {"A", "B", "C"}, {"B", "C"}, {"C"}}

Итерация завершена, добавьте пустой набор:

sets = {{"A"}, {"A", "B"}, {"B"}, {"A", "C"}, {"A", "B", "C"}, {"B", "C"}, {"C"}, {}}

Размер наборов 2^|set| = 2 ^ 3 = 8, что правильно.


Пример реализации на Java:

public static <T> List<List<T>> powerSet(List<T> input) {
  List<List<T>> sets = new ArrayList<>();
  for (T element : input) {
    for (ListIterator<List<T>> setsIterator = sets.listIterator(); setsIterator.hasNext(); ) {
      List<T> newSet = new ArrayList<>(setsIterator.next());
      newSet.add(element);
      setsIterator.add(newSet);
    }
    sets.add(new ArrayList<>(Arrays.asList(element)));
  }
  sets.add(new ArrayList<>());
  return sets;
}

Ввод: [A, B, C]

Выход: [[A], [A, C], [A, B], [A, B, C], [B], [B, C], [C], []]

person Cristian    schedule 23.03.2016
comment
Если бы вы добавили {} в начале (а не в конце), вам не пришлось бы явно вставлять одноэлементные наборы при каждом проходе через внешний цикл. - person John Coleman; 23.03.2016
comment
@JohnColeman Привет, Джон, если бы мы добавили пустой набор в начале, мы бы перебирали наборы слишком много раз. После первой итерации у нас будет {{A},{A}}, что неверно. Вставка пустого набора также выполняется вне любых циклов. Не могли бы вы поделиться кодом для объяснения? - person Cristian; 23.03.2016
comment
Но если у вас есть {} в начале, разве у вас не будет {"A"}, {} после одного прохода? Вы берете существующий sets и создаете в нем копию каждого набора, к которому добавляете новый элемент. Поскольку вы добавляете A к копии, я не вижу, как A проникает в пустой набор. В конце концов, когда вы делаете это с B в своем цикле, вы получаете {A,B}, но все еще имеете {A} - это {A} не заменяется на {A,B}. Вы должны вставить пустой набор вне любого цикла, но перед циклами, и в этом случае добавление синглетонов внутри цикла излишне. - person John Coleman; 23.03.2016
comment
@JohnColeman Если я начну с пустого набора {{}}, то по мере повторения наборов я возьму пустой набор и добавлю к нему «A». Затем я добавлю новый набор, содержащий «А», к существующим наборам. Запустив код с вашим предложением, я получаю следующее после первой итерации: [[], [A], [A]] как и ожидалось. Запустив новый алгоритм на {'A', 'B', 'C'}, я получаю [[], [C], [B], [B, C], [A], [A, C], [A, B], [A, B, C], [A], [A, C], [A, B], [A, B, C], [B], [B, C], [C]] - person Cristian; 23.03.2016
comment
Вы говорите, что затем я добавлю новый набор, содержащий «A», к существующим наборам, но почему вы все равно будете это делать? Суть моего комментария в том, что явное добавление элемента в виде синглтона (шаг 4 в вашем псевдокоде) не требуется, если вы инициализируете пустой набор - person John Coleman; 24.03.2016
comment
@Cristian Почему вы используете список, а не набор? не лучше ли использовать Set, чтобы гарантировать отсутствие дубликатов? - person SarahData; 12.06.2017
comment
@SarahM Я использую List, чтобы продемонстрировать, что этот алгоритм не создает дубликатов. - person Cristian; 12.06.2017

Набор мощности - это просто набор всех подмножеств для данного набора. Он включает все подмножества (с пустым множеством). Известно, что в этом наборе 2N элементов, где N — количество элементов в исходном наборе.

Для построения силового набора можно использовать следующее:

  • Создайте цикл, который перебирает все целые числа от 0 до 2N-1
  • Перейти к двоичному представлению для каждого целого числа
  • Каждое двоичное представление представляет собой набор из N битов (для меньших чисел добавьте ведущие нули). Каждый бит соответствует включению определенного члена множества в текущее подмножество.

Пример, 3 числа: a, b, c

number binary  subset
0      000      {}
1      001      {c}
2      010      {b}
3      011      {b,c}
4      100      {a}
5      101      {a,c}
6      110      {a,b}
7      111      {a,b,c}
person Alma Do    schedule 23.06.2014
comment
почему мы конвертируем в двоичный код? Я этого не понимаю. - person Pooja Khatri; 05.07.2018
comment
@PoojaKhatri каждый бит в двоичном числе указывает, присутствует ли элемент в текущем подмножестве или нет. Проверьте лучший ответ для лучшего объяснения. - person Nikhil Vandanapu; 03.09.2018

Ну, вам нужно сгенерировать все подмножества. Для набора размера n существует 2n подмножеств.

Один из способов — перебрать числа от 0 до 2n - 1 и преобразовать каждое в список двоичных цифр, где 0 означает исключить этот элемент, а 1 означает включить его.

Другой способ - с рекурсией, разделяй и властвуй.

person Tom Zych    schedule 23.06.2014
comment
Я знаю, что эта ветка устарела, но мне очень интересно узнать больше о рекурсивной технике. Это было старое задание на Lisp в колледже, которое я так и не понял. И я все еще озадачен. - person SMBiggs; 12.02.2017
comment
@ScottBiggs Я тоже .. Это просто сбивает с толку! - person Koray Tugay; 05.08.2019
comment
Вы можете увидеть несколько рекурсивных примеров здесь: stackoverflow.com/questions/26332412 - person Tom Zych; 06.08.2019

Генерация всех комбинаций набора (с включением или без элемента). поясню на примере: 3 предмета в наборе (или списке). Возможным подмножеством будет:

000   
100   
010   
001
110
101
011
111   

Результат равен 2^(количество элементов в наборе).

Таким образом, мы можем сгенерировать все комбинации из N элементов (с помощью python) следующим образом:

def powerSet(items):

    N = len(items)

    for i in range(2**N):

        comb=[]
        for j in range(N):
            if (i >> j) % 2 == 1:
                comb.append(items[j])
        yield comb

for x in powerSet([1,2,3]):
    print (x)
person Amjad    schedule 25.12.2016

Вы получите что-то подобное, реализовав ответ с самым высоким рейтингом.

def printPowerSet(set,set_size):

    # set_size of power set of a set
    # with set_size n is (2**n -1)
    pow_set_size = (int) (math.pow(2, set_size));
    counter = 0;
    j = 0;

    # Run from counter 000..0 to 111..1
    for counter in range(0, pow_set_size):
        for j in range(0, set_size):

            # Check if jth bit in the 
            # counter is set If set then 
            # pront jth element from set 
            if((counter & (1 << j)) > 0):
                print(set[j], end = "");
        print("");
person Carlson Bimbuh    schedule 05.09.2018

Решение C#

Временная сложность и пространственная сложность: O (n * 2 ^ n)

 public class Powerset
    {


        /*
         P[1,2,3] = [[],[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]
             */
        public  List<List<int>> PowersetSoln(List<int> array)
        {

            /*
                We will start with an empty subset
                loop through the number in the array
                         loop through subset generated till and add the number to each subsets

              */

            var subsets = new List<List<int>>();
            subsets.Add(new List<int>());

            for (int i = 0; i < array.Count; i++)
            {
                int subsetLen = subsets.Count; 
                for (int innerSubset = 0; innerSubset < subsetLen; innerSubset++)
                {
                    var newSubset = new List<int>(subsets[innerSubset]);
                    newSubset.Add(array[i]);
                    subsets.Add(newSubset);
                }

            }

            return subsets;
        }
    }
person Code-EZ    schedule 20.05.2020

Пример кода Java:

void printPowerSetHelper(String s, String r) {
    if (s.length() > 0) {
        printPowerSetHelper(s.substring(1), r + s.charAt(0));
        printPowerSetHelper(s.substring(1), r);
    } 
    if (r.length() > 0) System.out.println(r);
}

void printPowerSet(String s) {
    printPowerSetHelper(s,"");
}
person ashwanilabs    schedule 06.11.2016