Алгоритм линейного перемешивания на месте


15

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

У Mathworld есть краткая страница о риффл-тасовке . В частности, меня интересует разновидность out-shuffle, которая преобразует входной массив 1 2 3 4 5 6 в 1 4 2 5 3 6. Обратите внимание, что в их определении длина ввода равна .2n

Это просто выполнить за линейное время, если у нас есть второй массив размером или более удобный. Сначала скопируйте последние n элементов в массив. Затем, предполагая индексирование на основе 0, скопируйте первые n элементов из индексов [0,1,2, ..., n-1] в [0, 2, 4, ..., 2n-2] . Затем скопируйте n элементов из второго массива обратно во входной массив, сопоставив индексы [0,1,2, ..., n-1] с [1,3,5, ..., 2n-1] . (Мы можем сделать немного меньше, чем это, потому что первый и последний элементы на входе не перемещаются.)nnn[0,1,2,...,n1][0,2,4,...,2n2]n[0,1,2,...,n1][1,3,5,...,2n1]

Один из способов сделать это на месте заключается в разложении перестановки на непересекающиеся циклы, а затем переупорядочении элементов в соответствии с каждым циклом. Опять же, при условии индексации на основе 0 перестановка, включенная в случай с 6 элементами, выглядит так:

σ=(012345024135)=(0)(5)(1243).

Как и ожидалось, первый и последний элементы являются фиксированными точками, и если мы переставим средние 4 элемента, мы получим ожидаемый результат.

К сожалению, мое понимание математики перестановок (и их ) в основном основано на википедии, и я не знаю, можно ли это сделать за линейное время. Может быть, перестановки, связанные с этой перестановкой, можно быстро разложить? Кроме того, нам даже не нужно полное разложение. Достаточно просто определить один элемент каждого из непересекающихся циклов, поскольку мы можем восстановить цикл по одному из его элементов. Возможно, нужен совершенно другой подход.LATEX

Хорошие ресурсы по смежной математике так же ценны, как и алгоритм. Благодарность!


Существует временное решение (с дополнительным пространством). Я не знаю никакого линейного решения. O ( 1 )O(nlgn)O(1)
Раду GRIGore

4
Это больше подходит для cs.stackexchange. В неоднородной модели времена всегда возможны. В этом случае это должно быть возможно даже равномерно. O(n)
Юваль Фильмус

1
@Radu Подобно этому вопросу , эта проблема, вероятно, не имеет решения, использующего только дополнительного пространства, но дополнительного пространства. O ( log n )O(1)O(logn)
Тайсон Уильямс

2
Я забираю свой комментарий (и голосую, чтобы закрыть) назад! (Хотя на этот вопрос ответили в литературе.)
Yuval Filmus

1
Я слышал этот вопрос от студента CS на прошлой неделе, который услышал его на собеседовании.
Джефф

Ответы:


12

Проблема на удивление нетривиальна. Вот хорошее решение Эллиса и Маркова « Стабильное слияние на месте» с помощью Perfect Shuffle (раздел 7). Эллис, Кран и Фан, « Вычисление циклов в совершенной перестановке», успешно выбирают «лидеров циклов» за счет увеличения объема памяти. Также связана хорошая статья Fich, Munro и Poblete , « Перестановка на месте» , которая дает общий алгоритм времени для модели оракула. Если доступен только оракул для перестановки, алгоритм требует логарифмического пространства; если у нас также есть оракул для обратного, он требует постоянного пространства.O(nlogn)

Теперь о решении Эллиса и Маркова. Сначала предположим, что . Затем вычисление совершенного перемешивания порядка сводится к вычислению совершенного перемешивания порядков и с вращением, предшествующим им. Вот доказательство на примере ( , , ): n x y n = 5 x = 3 y = 2 012 345 67 89 012 567 34 89 051627 3849n=x+ynxyn=5x=3y=2

012345678901256734890516273849

Эллис и Марков нашли простой способ вычислить идеальное перемешивание при , используя постоянное пространство и линейное время. Используя это, мы получаем алгоритм для вычисления идеального перемешивания для произвольного . Сначала напишите используя двоичную кодировку , и пусть . Поверните средние биты, перемешайте правые биты. Игнорирование битов, вращение средних битов и перетасовывание правых n n = 2 k 0 + + 2 k w n n i = 2 kn=2knn=2k0++2kwn n0ni=2ki++2kwn0 2 k 0 n 1 2 k 1 O ( n 0 + + n w ) = O ( n ) n t + 12k02k0n12k1биты. И так далее. Обратите внимание, что вращение легко, поскольку первые несколько вращающихся элементов функционируют как лидеры цикла. Общая сложность вращения составляет , поскольку . Общая сложность внутренних перемешиваний составляет .O(n0++nw)=O(n)O ( 2 k 0 + + 2 k w ) = O ( n )nt+1<nt/2O(2k0++2kw)=O(n)

Осталось показать, как вычислить идеальный случайный порядок при . Фактически, мы сможем определить лидеров цикла, следуя классической работе над ожерельями (Фредриксен и Майорана, Ожерелья из бисера в цветах и хари де Брюйна ; Фредриксен и Кесслер, Алгоритм генерации ожерелий из бисера в двух цветах ).k kn=2kkk

Какая связь? Я утверждаю, что случайная перестановка соответствует сдвигу вправо двоичного представления. Вот подтверждение для : Поэтому, чтобы найти лидеров цикла, нам нужно найти одного представителя из каждого класса эквивалентности вращения двоичных строк длины . Упомянутые выше документы дают следующий алгоритм генерации всех лидеров цикла. Начните с . На каждом этапе мы находимся в некоторой точке . Найти максимальный индекс нулевого бита,000 001 010 011 100 101 110 111 000 100 001 101 010 110 011 111 kn=8

000001010011100101110111000100001101010110011111
ka 1a k i0ka1akikпо чтобы получить , и пусть следующая точка будет . Всякий раз, когда , новая строка является лидером цикла.ik=di+r(a1ai11)da1arr=0

Например, когда генерируется последовательность 0000 , 0001 , 0010 , 0011 , 0101 , 0110 , 0111 , 1111 .n=16

0000,0001,0010,0011,0101,0110,0111,1111.

Лидеры цикла выделены.


3
2323k30,,3k

Хотя я думаю, что статья Джайна немного более прямолинейна, я предпочитаю более раннюю статью, а также более раннюю статью с наибольшим количеством голосов.
Джонни

6

Это был начальный вопрос на cs.stackexchange.com, и ответ здесь: /cs/332/in-place-algorithm-for-interleaving-an-array/400#400

Это объяснение статьи: http://arxiv.org/abs/0805.1598 .

k2k32k=2

Обратите внимание, что этот ответ имеет дело с перестановкой (т.е. Inshuffle), и наличие этого также облегчает решение этой проблемы (Outshuffle).j2jmod2n+1


Ха! Я полностью забыл об этом вопросе, даже если участвовал в обсуждении. Это означает, что я действительно не понимал, как это работает в то время.
Раду GRIGore

2

Что произойдет, если вы запишете риффл шаффл как функцию? Если - длина всего массива, пусть - длина массива после удаления первого и последнего элемента. Тогда перетасованный индекс индекса имеет вид если и если . Затем вы можете просто «перескочить указатель» через массив, меняя местами повторное применение функции.п = т - 2 я е ( я ) = 2 я я п / 2 е ( я ) = 2 ( яmn=m2if(i)=2iin/2i > n / 2f(i)=2(imodn/2)1i>n/2

Предполагая произвольный доступ, это будет линейное время, требующее дополнительных слов (для хранения значения массива при любом заданном индексе) и, таким образом, дополнительного пространства.O ( log n )O(1)O(logn)


Ах, подожди. Это предполагает, что все значения в перестановке riffle лежат на одном и том же цикле. Эта стратегия должна быть немного изменена, в зависимости от того, сколько существует непересекающихся циклов.
Роберт Робер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.