Есть строка, состоящая из разных скобок, необходимо проверить, закрыты ли все

Дана строка, состоящая из скобок, например: ([{}]). Скобки могут быть круглые: (), квадратные: [], фигурные: {}.

Необходимо проверить закрытость всех скобок в строке.

Примеры:

isValidBraces("()") === true
isValidBraces("[)") === false
isValidBraces("{}[]()") === true
isValidBraces("([{}])") === true
isValidBraces("())({}}{()][][") === false

Теория и алгоритм

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

Таблица соответствий (ожидаемая «пара»):

  • ()
  • []
  • {}

Пошаговый алгоритм:

  1. Создать пустой стек.
  2. Читать строку слева направо.
  3. Если символ — открывающая скобка, положить её в стек.
  4. Если символ — закрывающая скобка, то:
  • Если стек пуст, строка некорректна (закрывать нечего).
  • Иначе взять верхний элемент стека и проверить, что тип совпадает (например, ) закрывает только ().
  • Если тип совпал — удалить верхний элемент, иначе строка некорректна.
  1. После чтения всей строки строка корректна только если стек пуст (не осталось незакрытых скобок).

Схема работы на примере ([{}]):

Строка:  (  [  {  }  ]  )
Стек:    (                 // встретилась '(' -> push
         ( [               // встретилась '[' -> push
         ( [ {             // встретилась '{' -> push
         ( [               // встретилась '}' -> pop '{'
         (                 // встретилась ']' -> pop '['
         пусто             // встретилась ')' -> pop '('
Итог: стек пуст -> true
Проверка «количество открывающих равно количеству закрывающих» не является достаточной: строка "([)]" имеет одинаковое количество скобок, но является некорректной из-за неправильного порядка закрытия.

Разбор примеров и ошибок

Ошибки возникают в двух базовых ситуациях: закрывающая скобка встречается при пустом стеке или закрывающая скобка не соответствует верхушке стека (неправильный тип). Важно проверять обе ситуации сразу при обработке закрывающей скобки, чтобы завершать работу ранним возвратом false.

Разбор примеров из условия:

  • "()"( кладётся в стек, затем ) снимает (, стек пуст, результат true.
  • "[)"[ кладётся в стек, затем ) пытается закрыть (, но на верхушке [, результат false.
  • "{}[]()" → три независимые пары, стек каждый раз становится пустым, результат true.
  • "([{}])" → строго вложенные пары, верхушка каждый раз совпадает с нужным типом, результат true.
  • "())({}}{()][][" → в процессе обязательно появится либо преждевременное закрытие (стек пуст), либо несовпадение типов, либо останутся незакрытые скобки в конце, результат false.

Таблица «симптом → причина → что делать»:

СимптомПричинаПроверка в коде
Встречена )/]/} при пустом стекеЗакрывающая без пары слеваif (stack.length === 0) return false;
Типы не совпали (например, в стеке [, а пришло ))Нарушена вложенностьif (top !== needOpen) return false;
После прохода стек не пустОстались незакрытые открывающиеreturn stack.length === 0;

Кратко: проверка корректности скобок делается стеком — открывающие помещаются в стек, закрывающие сравниваются с верхушкой и удаляют её при совпадении; ошибка возникает при пустом стеке на закрытии, несовпадении типов или непустом стеке после прохода всей строки.