Используйте один deque (A) для хранения элементов и другого deque (B) для сохранения минимумов.
Когда x выставлен в очередь, push_back это на A и сохранить pop_backing B, пока задняя часть B не будет меньше x, затем push_back x на B.
при удалении A, pop_front A в качестве возвращаемого значения и если он равен фронту B, pop_front B. Также
при получении минимума A используйте переднюю часть B как возвращаемое значение.
dequeue и getmin, очевидно, O (1). Для операции enqueue рассмотрите push_back из n элементов. Существует n push_back для A, n push_back для B и не более n pop_back из B, потому что каждый элемент либо останется в B, либо будет выведен один раз из B. Во всех случаях есть операции O (3n), и поэтому амортизированная стоимость равна O (1), а также для очереди.
Наконец, причина, по которой этот алгоритм работает, заключается в том, что когда вы вставляете x в A, если в B есть элементы, большие, чем x, они никогда не будут минимальными, потому что x останется в очереди A дольше, чем любые элементы в B (очередь FIFO). Поэтому нам нужно выскочить элементы из B (сзади), которые больше, чем x, прежде чем нажимать x на B.
from collections import deque
class MinQueue(deque):
def __init__(self):
deque.__init__(self)
self.minq = deque()
def push_rear(self, x):
self.append(x)
while len(self.minq) > 0 and self.minq[-1] > x:
self.minq.pop()
self.minq.append(x)
def pop_front(self):
x = self.popleft()
if self.minq[0] == x:
self.minq.popleft()
return(x)
def get_min(self):
return(self.minq[0])