Лінійний алгоритм переміщення стрілецького часу на місці


15

Чи існує лінійний алгоритм переміщення гвинтівки на місці? Це алгоритм, який деякі особливо спритні руки здатні виконувати: рівномірно розділити вхідний масив рівного розміру, а потім переплетення елементів двох половинок.

MathWorld має коротку сторінку на гвинтівці перетасовки . Зокрема, мене цікавить різновид out-shuffle, який перетворює вхідний масив 1 2 3 4 5 6 в 1 4 2 5 3 6. Зауважте, що за їх визначенням довжина вводу становить 2n .

Це легко зробити в лінійний час, якщо у нас є другий масив розміром або більше під рукою. Спочатку скопіюйте останні елементів у масив. Потім, припускаючи індексацію на основі 0, скопіюйте перші елементів з індексів до . Потім скопіюйте елементів з другого масиву назад у вхідний масив, відображаючи індекси до . (Ми можемо виконати трохи менше роботи, ніж це, тому що перший і останній елементи на вході не рухаються.)ннн[0,1,2,...,н-1][0,2,4,...,2n−2]n[0,1,2,...,н-1][1,3,5,...,2n−1]

Один із способів спроби зробити це на місці включає декомпозицію перестановки на роз'єднані цикли та перестановку елементів відповідно до кожного циклу. Знову ж таки, якщо припустити індексацію на основі 0, перестановка, що бере участь у 6-елементному випадку, є

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

Як і очікувалося, перший і останній елементи є фіксованими точками, і якщо перестановити середні 4 елементи, ми отримаємо очікуваний результат.

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

Хороші ресурси з відповідної математики так само цінні, як і алгоритм. Спасибі!


Існує часове рішення (з додаткового простору). Я не знаю жодного лінійного рішення. O(nlg⁡n)O(1)
— Раду ГРИГоре

4
Це більше підходить для cs.stackexchange. У неоднорідній моделі завжди можливий час. У цьому випадку це можливо навіть рівномірно. O(n)
— Yuval Filmus

1
@Radu Аналогічно цьому питанню , ця проблема, ймовірно, не має рішення, використовуючи лише додатковий простір, але додатковий простір.O ( журнал n )O(1)O(log⁡n)
— Тайсон Вільямс

2
Я беру свій коментар (і голосую, щоб закрити) назад! (Хоча на питання дано відповідь у літературі.)
— Юваль Філіус

1
Це питання я чув минулого тижня від студента CS, який почув його на співбесіді.
— Джеффе

Відповіді:


12

Проблема напрочуд нетривіальна. Ось приємне рішення Елліса і Маркова, In-Situ, стабільне злиття шляхом ідеального перебору (розділ 7). Елліс, Кран і Вентилятор, обчислюючи цикли в ідеальній перестановці перетасування, вдаються вибрати "лідерів циклу" за рахунок більшої кількості пам'яті. Також пов’язаний приємний папір Фіха, Манро та Поблете , Permuting In Place , який дає загальний алгоритм часу n log n ) для моделі oracle. Якщо доступний лише оракул для перестановки, алгоритм вимагає логарифмічного простору; якщо ми також маємо оракул для зворотного, він вимагає постійного простору.O(nlog⁡n)

Тепер про рішення Елліса та Маркова. Спочатку припустимо, що . Тоді обчислення ідеального переміщення порядку 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 k i + ⋯ + 2 k w . Оберніть серединуn=2knn=2k0+⋯+2kwnni=2ki+⋯+2kw біт, перемістіть праву руку на 2 kn0 біт. Ігноруючиправу рукуна2 к 0 біт, поверніть серединуn1біт і перемістіть праву руку на2 k 1 біт. І так далі. Зауважте, що обертання просте, оскільки перші кілька елементів, що обертаються, виконують функцію лідерів циклу. Загальна складність обертання становитьO(n0+⋯+nw)=O(n), оскількиn t + 1 <nt/2. Загальна складність внутрішніх переміщень становитьO(2k02k0n12k1O(n0+⋯+nw)=O(n)nt+1<nt/2 .O(2k0+⋯+2kw)=O(n)

Залишилося показати, як обчислити ідеальне переміщення, коли . Насправді ми зможемо визначити лідерів циклу, дотримуючись класичної роботи над намистами (Фредріксен та Майорана, Кольє з намистин у k кольорах та послідовностях k -ary de Bruijn ; Фредріксен та Кесслер, Алгоритм генерування намиста з намистин у два кольори ).n=2kkk

Який зв’язок? Я стверджую, що перестановка перетасування відповідає правильному зміщенню бінарного представлення. Ось доказ на прикладі для : 000 001 010 011 100 101 110 111 000 100 001 101 010 110 011 111 Отже, щоб знайти лідери циклів, нам потрібно знайти одного представника з кожного класу еквівалентності обертання двійкові рядки довжиною k . Вищенаведені роботи дають наступний алгоритм для генерації всіх лідерів циклу. Почніть з 0 кn=8

000001010011100101110111000100001101010110011111
k0k . На кожному кроці ми в якийсь момент . Знайдіть максимальний індекс i нульового біта, розділітьa1…aki по i, щоб отримати k = d ⋅ i + r , і нехай наступна точка буде ( a 1 … a i - 1 1 ) d a 1 … a r . Щоразуkik=d⋅i+r(a1…ai−11)da1…ar ,новарядок є лідером циклу.r=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 ).

j→2jmod2n+1


Га! Я повністю забув про це питання, навіть якщо брав участь у дискусії. Це означає, що я не дуже розумів, як це працює в той час.
— Раду ГРИГо

2

mn=m−2if(i)=2⋅ii≤n/2f(i)=2⋅(imodn/2)−1i>n/2

O(1)O(log⁡n)


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