Коды Грея и задачи перебора
В данной статье будет показан математический подход к составлению алгоритмов на примере следующих вопросов и задач:
- Двоичные коды Грея. Их существование. Перебор подмножеств данного множества в порядке минимального изменения.
- Существование и реализация перебора подмножеств из k элементов в порядке минимального изменения.
Итак, приступим.
Двоичный код Грея
Двоичным кодом Грея порядка n называется последовательность всех
Пример кодов Грея порядка 2:
- 00
- 01
- 11
- 10
Нетрудно заметить, что такая последовательность не единственная(её как минимум можно обратить). Поэтому давайте разберемся в существовании двоичных кодов Грея других порядков и заодно выделим какой-то один вид таких последовательностей для дальнейшей работы.
Существование
Существование кодов Грея легко доказывается по индукции.
База —
Переход. Пусть
Коды Грея, полученные таким способом, называются рефлексивными или симметрично отраженными. В дальнейшем мы будем рассматривать именно рефлексивные двоичные коды Грея.
В качестве упражнения выпишите симметрично отраженные коды Грея порядка 3 по приведенной в доказательстве формуле:
А теперь перейдем к приложению кодов Грея для решения некоторых задач комбинаторики.
Перебор подмножеств данного множества в порядке минимального изменения
Рассмотрим следующую задачу: «Дано множество из n элементов. Требуется вывести все его подмножества в таком порядке, что каждое следующее подмножество получается из предыдущего удалением или добавлением ровно одного элемента(т.е. в порядке минимального изменения).»
Будем считать, что элементы нашего множества пронумерованы от 1 до n. Тогда любому набору элементов множества можно поставить в соответствие n-битный двоичный код: если i-ый элемент множества входит в набор, то i-ый бит кода равен единице, иначе нулю. Таким образом, перебор всех подмножеств сводится к перебору двоичных кодов порядка n, а перебор подмножеств в порядке минимального изменения — к перебору двоичных кодов Грея.
Идея алгоритма рекурсивного перебора кодов Грея непременно следует из доказательства их существования, а именно приведенного в нем рекуррентного соотношения
Перейдем к оценке сложности данного алгоритма. Очевидно, что дерево вызовов функции
В качестве упражнения читателю предлагается проанализировать следующий, более короткий, алгоритм рекурсивного перебора.
Пример
Также хотелось бы сказать о существовании итеративного алгоритма перебора и других полезных свойствах кодов Грея, которые не рассматриваются в данной статье, и о которых можно узнать из других источников, например Википедии.
А теперь давайте перейдем к последней и самой интересной задаче.
Перебор подмножеств из k элементов в порядке минимального изменения.
Начнем с постановки задачи: «Дано множество из n элементов. Требуется вывести все его подмножества, состоящие ровно из k элементов, в таком порядке, что каждое следующее подмножество получается из предыдущего заменой ровно одного элемента(т.е. в порядке минимального изменения).»
Здесь сразу приходит в голову идея алгоритма из предыдущей задачи, но выводить мы будем только те коды Грея, в которых ровно k единиц. При этом возникает вопрос о корректности этого алгоритма: нам никто не гарантирует, что соседние коды в последовательности
Введем некоторые обозначения:
-
— строка, получаемая конкатенацией символа x (m раз) и конкатенацией символа y (k раз). Пример: . -
— последовательность всех n-битных кодов с k единицами, в которой коды идут в том порядке, в котором они расположены в последовательности . -
— последовательность всех n-битных кодов с k единицами, в которой коды идут в том порядке, в котором они расположены в последовательности .
Лемма
Первый двоичный код сДоказательство
Доказывать будем индукцией поБаза —
Переход. Пусть формулы верны для
Теорема
Соседние двоичные коды в последовательностиДоказательство
Доказывать будем также индукцией поБаза —
Переход. Пусть теорема верна для
Теперь мы можем сформулировать замечательные следствия из теоремы.
- Наивный алгоритм, предложенный ранее, корректен, то есть, если в последовательности
оставить только те двоичные коды, в которых ровно k единиц, то они будут расположены в порядке минимального изменения(каждый следующий получается из предыдущего заменой одного элемента). - Последовательность
задается следующим рекуррентным соотношением: . Это можно проверить по индукции. - Последовательность
задается следующим рекуррентным соотношением: . Также проверяется по индукции.
Эти следствия можно и нужно использовать для написания программы рекурсивного перебора подмножеств из k элементов в порядке минимального изменения.
Перейдем к оценке сложности приведенного алгоритма. Заметим, что при углублении в рекурсию значение u всегда уменьшается. То есть мы сделаем не больше n углублений для достижения какого-то двоичного кода. Всего таких кодов —
Легко заметить, что дерево вызовов
Точная оценка асимптотики — далеко не тривиальный факт, который можно найти в книге Э.Рейнгольда, Ю.Нивергельта и Н.Део «Комбинаторные алгоритмы. Теория и практика», либо попытаться доказать самому.
На этом хотелось бы закончить статью. Спасибо за внимание и до скорых встреч.