Монотонный стек

Базовый Algorithms
≈ 2 мин чтения

Стек, из которого вовремя удаляют лишнее

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

Пример: следующий больший элемент

Для каждого элемента массива найдём первое значение справа, которое больше него. В стеке будем хранить индексы элементов, для которых ответ ещё не найден. Когда приходит более крупное значение, оно сразу завершает ожидание для подходящих элементов на вершине.

static int[] nextGreater(int[] numbers) {
    int[] result = new int[numbers.length];
    Arrays.fill(result, -1);
    Deque<Integer> stack = new ArrayDeque<>();

    for (int i = 0; i < numbers.length; i++) {
        while (!stack.isEmpty() && numbers[stack.peek()] < numbers[i]) {
            int index = stack.pop();
            result[index] = numbers[i];
        }
        stack.push(i);
    }

    return result;
}

Почему это O(n), хотя есть вложенный while

Каждый индекс попадает в стек ровно один раз и удаляется из него не более одного раза. Поэтому суммарное число операций со стеком линейно, а весь алгоритм работает за O(n) времени и использует O(n) дополнительной памяти.

Ключевой вопрос при таком подходе: когда кандидат становится бесполезным навсегда? Если на него можно ответить локальным сравнением с новым элементом, монотонный стек часто позволяет убрать повторные просмотры массива.