Сторнирование списка с использованием двух очередей

12

Этот вопрос основан на существующем вопросе о том, можно ли моделировать стек с использованием двух очередей с амортизированным раз на операцию стека. Ответ кажется неизвестным. Вот более конкретный вопрос, соответствующий особому случаю, когда сначала выполняются все операции PUSH, а затем все операции POP. Насколько эффективно можно изменить список из N элементов, используя две изначально пустые очереди? Юридические операции:O(1)N

  1. Поставьте в очередь следующий элемент из списка ввода (в конец любой очереди).
  2. Удалите элемент из заголовка любой из очередей и поставьте его снова (в конец любой очереди).
  3. Удалите элемент из заголовка любой очереди и добавьте его в список вывода.

Если список ввода состоит из элементов , как делает минимальное количество операций , необходимым для генерации списка перевернутого выходного [ N , N - 1 , . , , , 2 , 1 ] вести себя? Доказательство того, что он растет быстрее, чем O ( N ), было бы особенно интересно, так как это решило бы исходный вопрос в отрицательной форме.[1,2,...,N1,N][N,N1,...,2,1]O(N)


Обновление (15 января 2011 г.): проблема может быть решена в , как показано в представленных ответах и ​​их комментариях; и нижняя оценка Ω ( N ) тривиальна. Можно ли улучшить эти границы?O(NlogN)Ω(N)

mjqxxxx
источник
Чтобы уточнить: под «последним элементом из любой очереди» вы ссылаетесь на элемент в начале очереди?
Питер Тейлор
@Peter: Да, спасибо за разъяснения. Я редактировал вопрос.
mjqxxxx
Являются ли списки ввода и вывода стеками? Если так, то n op1s (в одну и ту же очередь), за которыми следует n op3s, делает наоборот, верно? Я думаю, что я должен упустить что-то важное.
Jbapple
@jbapple: Нет, они не стеки. Вам нужно записать элементы в список вывода в том порядке, в котором они были прочитаны из списка ввода.
mjqxxxx

Ответы:

11

Если N является степенью двойки, я полагаю, что операций O (N log N) достаточно даже для несколько более ограниченной проблемы, когда все элементы начинаются в одной из очередей и должны заканчиваться в обратном порядке в одной из очередей (без списки ввода и вывода).

В O (N) шагах можно начать со всех элементов в одной очереди, сыграть «один для вас, один для меня», чтобы разбить их на чередующиеся подмножества в другой очереди, а затем объединить их все обратно в одну очередь. С точки зрения двоичных представлений положений элементов, это реализует операцию поворота.

В O (N) шагах также можно извлечь пары элементов из одной очереди, поменять их местами, затем вернуть обратно, переворачивая все пары. В терминах двоичных представлений позиций элементов это дополняет младший бит позиции.

Повторяя O (log N) раз в случайном порядке и попарно меняем местами, мы можем дополнить все биты двоичных представлений позиций - это то же самое, что инвертировать список.

Дэвид Эппштейн
источник
Тогда, я думаю, вы можете разбить список на двоичное представление и поменять местами алгоритм O (n lg n).
jbapple
Я думал, что можно распространиться на все N, используя 2-3 дерева вместо двоичного, но, возможно, ваша идея проще. Но как отменить все O (log n) частей в O (n log n) полных шагов?
Дэвид Эппштейн
Время равно O (сумма (2 ^ i) lg (2 ^ i)) для i от 0 до [lg n], что говорит Вольфрам Альфа: O (n lg n): wolframalpha.com/input/?i=sum+ (2 ^ k) + log2 + (2 ^ k) + от + 0 + до + log2 + n
jbapple
Конечно, если вы можете перевернуть каждую из частей во времени, пропорциональное ее длине, умноженной на ее журнал, все готово. Но вы должны положить кусочки куда-нибудь после того, как вы перевернули их, и это может затруднить реверсирование оставшихся кусочков.
Дэвид Эппштейн
Проблема ставит «список вывода». Можем ли мы положить их там?
Jbapple
1

i=0N/21(N2i2)

Позволяет назвать две доступные очереди слева и справа. Вот основная идея этого алгоритма с предположением, что N четно:

  1. Считать значения из начального списка элементов и поместить все нечетные числа в левую очередь, а четные - в правую.
  2. На первом этапе самый быстрый способ вывести максимальное значение - это перенести N / 2-1 элементов из правой очереди в левую и вытолкнуть верхнее значение из правой очереди в список вывода.
  3. Теперь мы должны сделать то же самое для другой очереди - перенести элементы N / 2-1 из левой очереди в правую и вытолкнуть верхний элемент из левой очереди в список вывода.
  4. Поменяйте местами очереди и повторите шаги 2 и 3 для N = N-2

Легко понять, как алгоритм должен работать для нечетных N.

Elalfer
источник
Вы можете использовать $ ... $ для вставки кода LaTeX-ish (минус \).
Марк Рейтблатт