Генерация последовательно всей комбинации конечного множества с использованием лексикографического порядка и побитовой арифметики - PullRequest
4 голосов
/ 05 ноября 2011

Рассмотрим всю комбинацию длины 3 следующего массива целых чисел {1,2,3}.

Я бы хотел пройти через все комбинации длины 3, используя следующий алгоритм из wikipedia

// find next k-combination    
bool next_combination(unsigned long& x) // assume x has form x'01^a10^b in binary
{
  unsigned long u = x & -x; // extract rightmost bit 1; u =  0'00^a10^b
  unsigned long v = u + x; // set last non-trailing bit 0, and clear to the right; v=x'10^a00^b
  if (v==0) // then overflow in v, or x==0
    return false; // signal that next k-combination cannot be represented
  x = v +(((v^x)/u)>>2); // v^x = 0'11^a10^b, (v^x)/u = 0'0^b1^{a+2}, and x ← x'100^b1^a
  return true; // successful completion
}

Каким должно быть мое начальное значение для этого алгоритма для всех комбинаций {1,2,3}? Когда я получу выходные данные алгоритма, как мне восстановить комбинацию?

Я попробовал следующую прямую адаптацию, но я новичок в битовой арифметике и не могу сказать, правильно ли это.

// find next k-combination, Java    
int next_combination(int x)
{
  int u = x & -x; 
  int v = u + x; 
  if (v==0) 
    return v; 
  x = v +(((v^x)/u)>>2); 
  return x; 
}

Ответы [ 2 ]

3 голосов
/ 09 ноября 2011

Я нашел класс, который точно решит эту проблему.См. Класс CombinationGenerator здесь

https://bitbucket.org/rayortigas/everyhand-java/src/9e5f1d7bd9ca/src/Combinatorics.java

Чтобы восстановить комбинацию, выполните

for(Long combination : combinationIterator(10,3))       
    toCombination(toPermutation(combination);

Спасибо всем за ваш вклад.

1 голос
/ 25 сентября 2012

Я написал класс для работы с общими функциями для работы с биномиальным коэффициентом, к которому относится ваша проблема. Он выполняет следующие задачи:

  1. Выводит все K-индексы в хорошем формате для любого N, выбирающего K, в файл. K-индексы могут быть заменены более описательными строками или буквами. Этот метод делает решение проблемы такого типа довольно тривиальным.

  2. Преобразует K-индексы в соответствующий индекс записи в отсортированной таблице биномиальных коэффициентов. Этот метод намного быстрее, чем старые опубликованные методы, основанные на итерации. Это делается с помощью математического свойства, присущего треугольнику Паскаля. Моя газета говорит об этом. Я считаю, что я первый, кто открыл и опубликовал эту технику, но я могу ошибаться.

  3. Преобразует индекс в отсортированной таблице биномиальных коэффициентов в соответствующие K-индексы. Я считаю, что это может быть быстрее, чем ссылка, которую вы нашли.

  4. Использует Mark Dominus метод для вычисления биномиального коэффициента, который с гораздо меньшей вероятностью переполняется и работает с большими числами.

  5. Класс написан на .NET C # и предоставляет способ управления объектами, связанными с проблемой (если таковые имеются), используя общий список. Конструктор этого класса принимает значение bool, называемое InitTable, которое при значении true создаст общий список для хранения управляемых объектов. Если это значение равно false, таблица не будет создана. Таблицу не нужно создавать для выполнения 4 вышеуказанных методов. Методы доступа предоставляются для доступа к таблице.

  6. Существует связанный тестовый класс, который показывает, как использовать класс и его методы. Он был тщательно протестирован с 2 случаями, и никаких известных ошибок нет.

Чтобы прочитать об этом классе и загрузить код, см. Таблицу биномиального коэффициента .

Нетрудно преобразовать этот класс в Java.

...