2015-08-18 1 views
0

Мне нужно создать структуру данных, которая поддерживает следующее:Создайте структуру данных, которая поддерживает min, getLast, append, deleteLast в O (1), память ограничена n (не O (n)) + O (1)

getMinElement, getLastElement, insertElement, deleteLastElement - в O(1) время выполнения.

Память ограничена n (не O (n)) i.e. Вы можете хранить не более n элементов в данный момент. плюс O (1) память.

(Важно: указатели также считаются 1, поэтому связанный список, например, не может быть и речи).

Пример:

insert(6) 
min() -> 6 
insert(10) 
insert(5) 
min() -> 5 
insert(7) 
delete() 
min() -> 5 
delete() 
min() -> 6 
+1

Связанный список должен сделать это, хотя вам необходимо постоянно отслеживать наименьший элемент после каждой операции (что, кстати, приведет к тому, что 'delete' будет O (n), так как вам нужно будет выполнить полное повторное сканирование чтобы снова найти минимум) – Kevin

+5

Что делает 'delete'? –

+0

«Важная» часть не имеет смысла, поскольку существование метода 'delete' предполагает, что структура должна иметь * не менее * N элементов. И если добавить некоторые накладные расходы для самого структурирования - мы обречены с учетом этой заметки. Я думаю, вы неправильно поняли эту часть. –

ответ

4

Мы будем хранить самый последний минимум непосредственно. Это O (1) пространство.

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

В Python:

class MinStorage: 

    def __init__(self): 
     self.offsets = [] 
     self.min = None 

    def insertElement(self, element): 
     offset = 0 if self.min is None else (element - self.min) 
     self.offsets.append(offset) 
     if self.min is None or offset < 0: 
      self.min = element 

    def getMinElement(self): 
     return self.min 

    def getLastElement(self): 
     offset = self.offsets[-1] 
     if offset < 0: 
      # Last element defined a new minimum, so offset is an offset 
      # from the prior minimum, not an offset from self.min. 
      return self.min 
     else: 
      return self.min + offset 

    def deleteLastElement(self): 
     offset = self.offsets[-1] 
     self.offsets.pop() 
     if len(self.offsets) == 0: 
      self.min = None 
     if offset < 0: 
      self.min -= offset 

Вот версия, которая позволяет любому беззнаковое 16-разрядное целое число в качестве элемента, а только хранит беззнаковые 16-битные целые числа в массиве:

class MinStorage: 

    Cap = 65536 

    def __init__(self): 
     self.offsets = [] 
     self.min = None 

    def insertElement(self, element): 
     assert 0 <= element < self.Cap 
     offset = 0 if self.min is None else (element - self.min) 
     if offset < 0: offset += self.Cap 
     self.offsets.append(offset) 
     if self.min is None or element < self.min: 
      self.min = element 

    def getMinElement(self): 
     return self.min 

    def getLastElement(self): 
     element = self.__getLastElementUnchecked() 
     if element < self.min: 
      # Last element defined a new minimum, so offset is an offset 
      # from the prior minimum, not an offset from self.min. 
      return self.min 
     else: 
      return element 

    def deleteLastElement(self): 
     element = self.__getLastElementUnchecked() 
     self.offsets.pop() 
     if len(self.offsets) == 0: 
      self.min = None 
     elif element < self.min: 
      # Popped element defined a new minimum. 
      self.min = element 

    def __getLastElementUnchecked(self): 
     offset = self.offsets[-1] 
     element = self.min + offset 
     if element >= self.Cap: 
      element -= self.Cap 
     return element 

Обратите внимание, что на языке с 16-разрядной арифметикой без знака, которая обертывается при переполнении/потоке, вам не понадобятся проверки и корректировки с использованием self.Cap. В C (§6.2.5/9) и C++ (§3.9.1/4) необязательная арифметика требуется вести себя по мере необходимости. Однако Python не поддерживает 16-разрядную арифметику без знака.

+0

Ничего себе. Я удивлен. Этот подход работает, за исключением незначительной ошибки: в 'insertElement' self.min является' None' для первого шага, поэтому вы не можете его вычесть. – Aivean

+0

Это кажется правильным, мне нужно некоторое время, чтобы проверить, что это ответ, и плохо отметите его. Большое спасибо! – Nimrodshn

+1

Предположим, что числовые значения представляют собой неподписанные 16-битные целые числа. Таким образом, допустимая последовательность может быть 65000,0, 64000 и т. Д. В вашем решении список различий будет включать в себя -65000, +64000, которые не могут быть сохранены в 16-разрядном целое. Вам понадобится 17 бит ..... или иначе ограничьте ввод беззнаковыми 15-битными номерами (вместо 16 бит). Такая же проблема существует для ввода 32/64 бит (подпись или без знака). Это потому, что вы фактически используете (= расточительствование) 1 бит в каждом номере .... –

1

Используйте стек, который хранит как вставленное значение и текущую мин. Текущий min обновляется при вставке (push) значения, сравнивая значение с текущим min и при удалении (pop) значение, отображающее текущее значение min из верхней части стека.

+0

Для хранения предыдущих минимальных значений потребуется дополнительная память O (N). Это нарушает требования OP. – Aivean

+0

@Aivean это требование bs, ОП получил много чего не так. Это решение O (N), которое является оптимальным по сложности пространства, а также временной сложностью (O (1) для всех операций). –

+0

Я согласен, но, видимо, существует решение, удовлетворяющее требованиям OP (однако подходит только для числовых элементов). Проверьте принятый ответ. – Aivean

0

Если вы можете предположить, что «данные находятся в диапазоне от 0 до 255 (int8)», и вам разрешено хранить целое число в два раза больше точности (int16), тогда вы можете сохранить «кумулятивный минимум» в верхний байт и точка данных в нижнем байте. Помимо этого, я не считаю, что это возможно в рамках ограничений, которые вы указали.

Смежные вопросы