Прежде всего, мне действительно нравится решение Джонатана , но я чувствую, что могу добавить и некоторые интересные идеи.
Основное наблюдение состоит в том, что массив P
состоит изнесколько петель.
Давайте рассмотрим p = {1, 4, 3, 2, 0, 5}
.Есть три цикла: 0 => 1 => 4 => 0
, 2 => 3 => 2
и 5 => 5
.И чтобы заменить переменные рядом с одним циклом, нам вообще не нужна дополнительная память.Мы просто пройдем через это, как это
do {
a[i] = a[p[i]];
i = p[i];
} while (i != first_i);
(хотя последний элемент необходимо уделить особое внимание.) Полная рабочая версия:
for (int i = 0; i < n; ++i) {
if (p[i] < 0) {
// been at index 'i' already
continue;
}
// new loop found
int j = i;
int first_value = a[i]; // to be put in last position in the chain
int prev_j; // we always store previous 'j' index
do {
a[j] = a[p[j]];
prev_j = j;
j = p[j]; // move to next 'j'
p[prev_j] = -1; // mark element as processed
} while (i != j);
a[prev_j] = first_value;
}
Единственная проблема с моимРешение в том, что он использует массив p
, чтобы пометить элемент как «обработанный».Некоторые интервьюеры могут считать это нормальным, другие - нет, в зависимости от решения, которое они имеют в виду.