вставить, удалить, максимум в O (1) - PullRequest
34 голосов
/ 09 августа 2010

Может кто-нибудь сказать мне, какая структура данных поддерживает операции вставки / удаления / максимального в O (1)?

Ответы [ 7 ]

56 голосов
/ 09 августа 2010

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

Разработка структуры данных в виде стека, которая выполняет операции push, pop и min (или max) в O (1)время.Ограничений по пространству нет.

Ответ таков: вы используете два стека: основной стек и минимальный (или максимальный) стек.

Так, например, после нажатия 1, 2,3,4,5 на стек, ваши стеки будут выглядеть следующим образом:

MAIN   MIN
+---+  +---+
| 5 |  | 1 |
| 4 |  | 1 |
| 3 |  | 1 |
| 2 |  | 1 |
| 1 |  | 1 |
+---+  +---+

Однако, если вы добавите 5,4,3,2,1, стеки будут выглядеть такэто:

MAIN   MIN
+---+  +---+
| 1 |  | 1 |
| 2 |  | 2 |
| 3 |  | 3 |
| 4 |  | 4 |
| 5 |  | 5 |
+---+  +---+

Для 5,2,4,3,1 у вас будет:

MAIN   MIN
+---+  +---+
| 1 |  | 1 |
| 3 |  | 2 |
| 4 |  | 2 |
| 2 |  | 2 |
| 5 |  | 5 |
+---+  +---+

и т. д.

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

17 голосов
/ 24 августа 2014

Следующее решение использует O (1) дополнительную память и O (1) время для операций max, push и pop. Сохраняйте переменную max, которая будет отслеживать текущий элемент max в любой конкретный момент времени. Давайте используем тот факт, что при обновлении max все элементы в стеке должны быть меньше, чем новый элемент max. Когда происходит операция push и новый элемент (newElement) больше текущего max, мы помещаем max + newElement в стек и обновляем max = newElement.

Когда мы выполняем операцию pop и обнаруживаем, что текущий вытолкнутый элемент больше текущего max, тогда мы знаем, что это место, где мы обновили наш стек, чтобы он содержал max + elem. Таким образом, фактический элемент, который должен быть возвращен, это max, а max = poppedElem - max.

Например. если мы нажимаем 1, 2, 3, 4, 5, переменная stack и max будет выглядеть следующим образом:

MAIN       Value of MAX
+---+      +---+
| 9 |      max = | 5 |
| 7 |      max = | 4 |
| 5 |      max = | 3 |
| 3 |      max = | 2 |
| 1 |      max = | 1 |
+---+      +---+

Теперь допустим, что мы вытолкнули элемент, мы в основном вытолкнем элемент max (поскольку top> max) и обновим элемент max до (top-max)

MAIN       Value of MAX
+---+      +---+
| 7 |      max = | 4 | = (9-5)
| 5 |      max = | 3 |
| 3 |      max = | 2 |
| 1 |      max = | 1 |
+---+      +---+

Теперь предположим, что мы нажимаем цифры 5, 4, 3, 2, 1, стек будет выглядеть так:

MAIN       Value of MAX
+---+      +---+
| 1 |      max = | 5 |
| 2 |      max = | 5 |
| 3 |      max = | 5 |
| 4 |      max = | 5 |
| 5 |      max = | 5 |
+---+      +---+

Когда мы выталкиваем, вершина стека выталкивается, так как top

Ниже приведен псевдокод для каждой операции для лучшего понимания.

Elem max;
void Push(Elem x){
    if x < max :
        push(x);
    else{
        push(x+max);
        max = x;
    }
}
Elem Pop(){
    Elem p = pop();
    if |p| < |max|:
        return p;
    else{
        max = p - max;
        return max;
    }
}
Elem Max(){
    return max;
}

push и pop - обычные операции со стеком. Надеюсь, это поможет.

14 голосов
/ 09 августа 2010

@ Комментарий KennyTM указывает на важную недостающую деталь - вставьте куда, и удалите откуда. Поэтому я предполагаю, что вы всегда хотите вставлять и удалять только с одного конца, как стек.

Вставка (push) и Delete (pop) - O (1).

Чтобы получить Макс в O (1), используйте дополнительный стек для записи текущего максимума, который соответствует основному стеку.

3 голосов
/ 09 августа 2010

Если вы используете только сравнения, вам будет сложно найти такую ​​структуру данных.

Например, вы можете вставить n элементов, получить максимум, удалить максимум и т.д.) время, в то время как теоретическая нижняя граница - Омега (nlogn).

0 голосов
/ 13 декабря 2016

Как некоторые уже указали, в вопросе не хватает информации. Вы не указываете, куда вставлять / удалять, ни характер данных, с которыми мы имеем дело.

Некоторые идеи, которые могут быть полезны: Вы говорите,

вставка / удаление / максимальная операция в O (1)

обратите внимание, что если мы можем вставить, удалить и найти maximun в O (1), то мы можем использовать эту гипотетическую технику для сортировки в O (n), потому что мы можем вставить n элементов и затем взять max / delete и мы их все отсортируем. Доказано, что никакой алгоритм сортировки, основанный на сравнениях, не может сортировать меньше, чем O (nlogn), поэтому мы знаем, что никакой подход на основе сравнения не будет работать. Фактически, одним из самых быстрых способов сделать это является очередь Бродала, но время ее удаления превышает O (1).

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

Но, возможно, это не было что-то общее. Другая интерпретация заключается в том, что вставка / удаление - это классические стеки. В этом ограниченном случае вы можете использовать решение с двойным стеком, которое Can Berk Güder дал вам.

0 голосов
/ 08 сентября 2016

Программа ниже отслеживает максимальное количество элементов в стеке таким образом, чтобы в любой момент времени верхний указатель давал нам максимум в стеке: Таким образом, max будет O (1), и мы можем найти max по max [N]

ITEM   MAX

+---+  +---+
| 1 |  | 1 |
| 10|  | 10|
| 9 |  | 10|
| 19|  | 19| <--top
+---+  +---+

Java-программа:

public class StackWithMax {

private int[] item;
private int N = 0;
private int[] max;

public StackWithMax(int capacity){
    item = new int[capacity];//generic array creation not allowed
    max = new int[capacity];
}

public void push(int item){
    this.item[N++] = item;
    if(max[N-1] > item) {
        max[N] = max[N-1];
    } else {
        max[N] = item;
    }
}

public void pop() {
    this.item[N] = 0;
    this.max[N] = 0;
    N--;
}

public int findMax(){
    return this.max[N];
}
public static void main(String[] args) {
    StackWithMax max = new StackWithMax(10);
    max.push(1);
    max.push(10);
    max.push(9);
    max.push(19);
    System.out.println(max.findMax());
    max.pop();
    System.out.println(max.findMax());


}

}
0 голосов
/ 09 августа 2010

Хеш-таблица может поддерживать вставку / удаление в O (1), хотя понятия о максимуме нет. Вам, вероятно, придется как-то самим это отслеживать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...