Существует ли линейный алгоритм временного перемешивания на месте? Это алгоритм, который способны выполнить некоторые особенно ловкие руки: равномерно разделить входной массив четного размера, а затем чередовать элементы двух половинок.
У Mathworld есть краткая страница о риффл-тасовке . В частности, меня интересует разновидность out-shuffle, которая преобразует входной массив 1 2 3 4 5 6 в 1 4 2 5 3 6. Обратите внимание, что в их определении длина ввода равна .
Это просто выполнить за линейное время, если у нас есть второй массив размером или более удобный. Сначала скопируйте последние n элементов в массив. Затем, предполагая индексирование на основе 0, скопируйте первые n элементов из индексов [0,1,2, ..., n-1] в [0, 2, 4, ..., 2n-2] . Затем скопируйте n элементов из второго массива обратно во входной массив, сопоставив индексы [0,1,2, ..., n-1] с [1,3,5, ..., 2n-1] . (Мы можем сделать немного меньше, чем это, потому что первый и последний элементы на входе не перемещаются.)
Один из способов сделать это на месте заключается в разложении перестановки на непересекающиеся циклы, а затем переупорядочении элементов в соответствии с каждым циклом. Опять же, при условии индексации на основе 0 перестановка, включенная в случай с 6 элементами, выглядит так:
Как и ожидалось, первый и последний элементы являются фиксированными точками, и если мы переставим средние 4 элемента, мы получим ожидаемый результат.
К сожалению, мое понимание математики перестановок (и их ) в основном основано на википедии, и я не знаю, можно ли это сделать за линейное время. Может быть, перестановки, связанные с этой перестановкой, можно быстро разложить? Кроме того, нам даже не нужно полное разложение. Достаточно просто определить один элемент каждого из непересекающихся циклов, поскольку мы можем восстановить цикл по одному из его элементов. Возможно, нужен совершенно другой подход.
Хорошие ресурсы по смежной математике так же ценны, как и алгоритм. Благодарность!