Это классический вопрос о структурах данных.Интуиция, лежащая в основе этой проблемы, заключается в следующем: единственный способ изменить максимум и минимум - это вставить новое значение в стек или вытолкнуть новое значение из стека.Учитывая это, предположим, что на каждом уровне в стеке вы отслеживаете максимальные и минимальные значения в или ниже этой точки в стеке.Затем, когда вы помещаете новый элемент в стек, вы можете легко (за время O (1)) вычислить максимальное и минимальное значение в любом месте стека, сравнивая только что добавленный элемент с текущим максимумом и минимумом.Точно так же, когда вы выталкиваете элемент, вы выставляете элемент в стеке на один шаг ниже вершины, который уже имеет максимальные и минимальные значения в оставшейся части стека, хранящейся рядом с ним.
Визуальночто у нас есть стек и добавляем значения 2, 7, 1, 8, 3 и 9 в указанном порядке.Мы начинаем с нажатия 2, и поэтому мы помещаем 2 в наш стек.Поскольку 2 теперь является самым большим и наименьшим значением в стеке, мы записываем это:
2 (max 2, min 2)
Теперь давайте нажмем 7. Так как 7 больше 2 (текущий максимум), мы получаемthis:
7 (max 7, min 2)
2 (max 2, min 2)
Обратите внимание, что прямо сейчас мы можем считывать максимум и минимум стека, посмотрев на вершину стека и увидев, что 7 - это максимум, а 2 - это минимум.Если мы теперь нажмем 1, мы получим
1 (max 7, min 1)
7 (max 7, min 2)
2 (max 2, min 2)
Здесь мы знаем, что 1 - это минимум, поскольку мы можем сравнить 1 с кэшированным минимальным значением, хранящимся в стеке (2).В качестве упражнения убедитесь, что вы понимаете, почему после добавления 8, 3 и 9 мы получаем следующее:
9 (max 9, min 1)
3 (max 8, min 1)
8 (max 8, min 1)
1 (max 7, min 1)
7 (max 7, min 2)
2 (max 2, min 2)
Теперь, если мы хотим запросить max и min, мы можем сделать это в O (1) просто считывая сохраненные значения max и min над стеком (9 и 1 соответственно).
Теперь предположим, что мы выскакиваем из верхнего элемента.Это дает 9 и изменяет стек так:
3 (max 8, min 1)
8 (max 8, min 1)
1 (max 7, min 1)
7 (max 7, min 2)
2 (max 2, min 2)
И теперь обратите внимание, что максимум этих элементов равно 8, точно правильный ответ!Если мы затем нажмем 0, мы получим это:
0 (max 8, min 0)
3 (max 8, min 1)
8 (max 8, min 1)
1 (max 7, min 1)
7 (max 7, min 2)
2 (max 2, min 2)
И, как вы можете видеть, макс и мин вычисляются правильно.
В целом, это приводит к реализациистек, который имеет O (1) push, pop, find-max и find-min, что асимптотически так же хорошо, как и получается.Я оставлю реализацию в качестве упражнения.:-) Однако вы можете рассмотреть возможность реализации стека с использованием одного из стандартных методов реализации стека, таких как использование динамического массива или связанного списка объектов, каждый из которых содержитэлемент стека, мин и макс.Вы можете сделать это легко, используя ArrayList
или LinkedList
.В качестве альтернативы вы можете использовать предоставленный класс Java Stack
, хотя IIRC имеет некоторые накладные расходы из-за синхронизации, которая может быть ненужной для этого приложения.
Интересно, что после того, как вы создали стек с этими свойствами, выможет использовать его как строительный блок для построения очереди с такими же свойствами и гарантиями времени.Вы также можете использовать его в более сложной конструкции для создания двусторонней очереди с этими свойствами.
Надеюсь, это поможет!
РЕДАКТИРОВАТЬ: Если вы 'любопытно, у меня есть C ++ реализации минимальный стек и вышеупомянутая минимальная очередь на моем личном сайте.Надеюсь, это показывает, как это может выглядеть на практике!