Чи існує лінійний алгоритм переміщення гвинтівки на місці? Це алгоритм, який деякі особливо спритні руки здатні виконувати: рівномірно розділити вхідний масив рівного розміру, а потім переплетення елементів двох половинок.
MathWorld має коротку сторінку на гвинтівці перетасовки . Зокрема, мене цікавить різновид out-shuffle, який перетворює вхідний масив 1 2 3 4 5 6 в 1 4 2 5 3 6. Зауважте, що за їх визначенням довжина вводу становить .
Це легко зробити в лінійний час, якщо у нас є другий масив розміром або більше під рукою. Спочатку скопіюйте останні елементів у масив. Потім, припускаючи індексацію на основі 0, скопіюйте перші елементів з індексів до . Потім скопіюйте елементів з другого масиву назад у вхідний масив, відображаючи індекси до . (Ми можемо виконати трохи менше роботи, ніж це, тому що перший і останній елементи на вході не рухаються.)
Один із способів спроби зробити це на місці включає декомпозицію перестановки на роз'єднані цикли та перестановку елементів відповідно до кожного циклу. Знову ж таки, якщо припустити індексацію на основі 0, перестановка, що бере участь у 6-елементному випадку, є
Як і очікувалося, перший і останній елементи є фіксованими точками, і якщо перестановити середні 4 елементи, ми отримаємо очікуваний результат.
На жаль, моє розуміння математики перестановок (та їх ) здебільшого базується на вікіпедії, і я не знаю, чи можна це зробити в лінійний час. Може, перестановки, що беруть участь у цьому перетасуванні, можуть швидко розкластись? Крім того, нам навіть не потрібне повне розкладання. Достатньо лише визначити один елемент кожного з розрізнених циклів, оскільки ми можемо реконструювати цикл з одного з його елементів. Можливо, потрібен зовсім інший підхід.
Хороші ресурси з відповідної математики так само цінні, як і алгоритм. Спасибі!