Предполагая, что вы имеете в виду O (1) памяти (или в зависимости от модели O (log n)), а не без дополнительной памяти , существует алгоритм с линейным временем на месте.
Эта статья: http://arxiv.org/abs/0805.1598 имеет алгоритм для случая, когда у вас есть
a1 ... an b1 ... bn
и вы хотите преобразовать в
b1 a1 b2 a2 ... bn an
.
также упоминает, что вы можете обобщить это на другие k-way shuffles.В вашем случае k = 3.
Алгоритм в статье даст следующее:
Начните с a1 a2 ... an b1 b2 ... bn c1 c2 ... cn
и преобразуйте в
c1 b1 a1 c2 b2 a2 ... cn bn an
Еще один проход через это, и вы можете легко получить a1 b1 c2 a2 b2 c2 ... an bn cn
.
Теперь, чтобы обобщить алгоритм в статье, нам нужно выбрать простое число p, такое, что k является примитивным корнем из p ^2.
Для k = 3 подойдет p = 5.
Теперь, чтобы применить алгоритм, сначала нужно найти наибольшее m
Примечание: это произойдет только тогда, когда 3m + 1 - это даже мощность 5. Таким образом, вы можете работать со степенями 25, пытаясь найти m.(5 ^ нечетное - 1 не делится на 3).
Как только вы найдете m,
Вы перетасуете массив в
[a1 a2 ... am b1 b2 ... bm c1 c2 ... cm] [a(m+1) ... an b(m+1) ... bn c(m+1) ... cn]
и затем используйте метод цикла (см. статью) для первых 3-х элементов, используя степени 5 (включая 1 = 5 ^ 0) в качестве отправных точек различных циклов) и выполните хвостовую рекурсию для остальных
Теперь, чтобы преобразовать a1 a2 ... an b1 b2 ... bn c1 c2 ... cn
в
[a1 a2 ... am b1 b2 ... bm c1 c2 ... cm] [a(m+1) ... an b(m+1) ... bn c(m+1) ... cn]
, вы сначала делаете циклический сдвиг, чтобы получить
a1 a2 ... am [b1 b2 bm a(m+1) .. an] b(m+1) .. bn c1 c2 ... cn
(элементы в квадратных скобках - это те, которые были сдвинуты)
Затем выполните циклический сдвиг, чтобы получить
a1 a2 ... am b1 b2 bm a(m+1) .. an [c1 c2 ..cm b(m+1) .. bn ] c(m+1) ... cn
И затем заключительный сдвиг к
a1 a2 ... am b1 b2 bm [c1 c2 ..cm a(m+1) .. an ] b(m+1) .. bn c(m+1) ... cn
Обратите внимание, что циклический сдвиг может быть выполнен за O (n) времени и O (1) пространства.
Итак, весь алгоритмO (n) время и O (1) пространство.