Упорядоченный список с произвольным доступом и удалением O (1)

Существует ли структура данных со следующими свойствами:

  • Элементы хранятся в некотором порядке
  • Доступ к элементу по заданному индексу занимает время O (1) (возможно, амортизированное)
  • Удаление элемента требует амортизации O (1) времени и соответствующим образом изменяет индексы (поэтому, если элемент 0 удаляется, следующий доступ к элементу 0 должен возвращать старый элемент 1)

В контексте я уменьшил вопрос алгоритма от соревнований по программированию до:

В запросах m верните k th наименьшее положительное число, которое еще не было возвращено. Вы можете предположить, что возвращаемое число меньше некоторой константы n.

Если структура данных выше существует, вы можете сделать это в O(m) раз, создав список чисел от 1 до n. Затем для каждого запроса найдите элемент с индексом k и удалите его. Во время самого конкурса мое решение оказалось O(m^2) на определенных входах.

Я уверен, что вы можете сделать это в O(m log m) с бинарными деревьями поиска, но мне интересно, доступен ли идеальный O(m). Материал, который я нашел в Интернете, как правило, близок, но не совсем там - сложная часть состоит в том, что удаляемые элементы могут быть из любого места в списке.

Ответ 1

  • > удаление O(1) возможно с помощью linked list

    каждый элемент имеет указатель на следующий и предыдущий элемент, поэтому удаление просто удаляет элемент и устанавливает указатели его соседей, например:

    element[ix-1].next=element[ix+1].prev
    
  • доступ к упорядоченным элементам с индексом в O(1) может выполняться с помощью indexed arrays

    поэтому у вас есть неупорядоченный массив вроде dat[] и индексный массив, например idx[], доступ к элементу ix справедлив:

    dat[idx[ix]]
    
  • Теперь проблема состоит в том, чтобы сразу получить эти свойства

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

    если у вас есть только индексный массив, тогда удаление также O(N)

    если у вас есть индекс в какой-либо форме древовидной структуры, тогда удаление может быть близко к O(log(N)), но доступ будет также о O(log(N))

Ответ 2

Я считаю, что есть структура, которая будет делать это в O (n) времени, где n - количество удаленных точек, а не общий размер. Поэтому, если номер, который вы удаляете, мал по сравнению с размером массива, он близок к O (1).

В принципе, все данные хранятся в массиве. Также существует очередь приоритетов для удаленных элементов. Инициализируйте так:

Data = [0, 1, 2, ..., m]
removed = new list

Затем, чтобы удалить элемент, вы добавляете его исходный индекс (см. ниже, как это сделать) в очередь приоритетов (которая сортируется по размеру элемента с наименьшим по фронту) и оставляют массив как есть. Поэтому удаление третьего элемента:

Data = [0, 1, 2, 3,..., m]
removed = 2

Тогда что теперь четвертое и было пятым:

Data = [0, 1, 2, 3,..., m]
removed = 2 -> 4

Тогда что теперь третье и было 4-м:

Data = [0, 1, 2, 3,..., m]
removed = 2 -> 3 -> 4

Теперь, чтобы получить доступ к элементу, вы начинаете с него индексом. Затем вы итерации по удаленному списку, каждый раз увеличивая индекс на единицу, пока не достигнете элемента, который больше, чем увеличенное значение индекса. Это даст вам исходный индекс (т.е. Позицию в Data) элемента, который вы ищете, и является индексом, необходимым для удаления.

Эта операция итерации по очереди эффективно увеличивает индекс по количеству элементов, которые были удалены.

Извините, если я не объяснил очень хорошо, это было ясно в моей голове, но трудно записать.

Комментарии:

  • Доступ - O (n), с n количеством удаленных элементов
  • Удаление примерно в два раза превышает время доступа, но все же O (n)
  • Недостатком является то, что использование памяти не сокращается при удалении.
  • Возможно, "переинициализировать", когда удаленный список будет большим до reset использования памяти, времени доступа и удаления. Эта операция принимает O (N), с N общим размером массива.

Таким образом, это не совсем то, что ищет OP, но в правильной ситуации может быть близко.