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


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,...,2n2]n[0,1,2,...,н-1][1,3,5,...,2n1]

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

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

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

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

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


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

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

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

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

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

Відповіді:


12

Проблема напрочуд нетривіальна. Ось приємне рішення Елліса і Маркова, In-Situ, стабільне злиття шляхом ідеального перебору (розділ 7). Елліс, Кран і Вентилятор, обчислюючи цикли в ідеальній перестановці перетасування, вдаються вибрати "лідерів циклу" за рахунок більшої кількості пам'яті. Також пов’язаний приємний папір Фіха, Манро та Поблете , Permuting In Place , який дає загальний алгоритм часу n log n ) для моделі oracle. Якщо доступний лише оракул для перестановки, алгоритм вимагає логарифмічного простору; якщо ми також маємо оракул для зворотного, він вимагає постійного простору.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 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 нульового біта, розділітьa1aki по i, щоб отримати k = d i + r , і нехай наступна точка буде ( a 1a i - 1 1 ) d a 1a r . Щоразуkik=di+r(a1ai11)da1ar ,новарядок є лідером циклу.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 ).

j2jmod2n+1


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

2

mn=m2if(i)=2iin/2f(i)=2(imodn/2)1i>n/2

O(1)O(logn)


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