Задачи со скобками

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

Стек хранит незакрытые скобки

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

static boolean isValid(String text) {
    Deque<Character> stack = new ArrayDeque<>();

    for (char ch : text.toCharArray()) {
        if (ch == '(' || ch == '[' || ch == '{') {
            stack.push(ch);
            continue;
        }

        if (stack.isEmpty()) {
            return false;
        }

        char open = stack.pop();
        if ((ch == ')' && open != '(')
                || (ch == ']' && open != '[')
                || (ch == '}' && open != '{')) {
            return false;
        }
    }

    return stack.isEmpty();
}

Почему одной проверки количества недостаточно

Строка "([)]" содержит одинаковое число открывающих и закрывающих скобок, но порядок неправильный: круглая скобка пытается закрыться, пока сверху стека находится квадратная. Стек хранит именно структуру вложенности, а не просто счётчик.

Две типичные ошибки

Если закрывающая скобка приходит при пустом стеке, ей нечего закрывать — строка неверна сразу. Если после обработки всей строки стек не пуст, часть открывающих скобок так и не получила пару. Обе проверки обязательны.

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