Напишите функцию, которая проверяет правильность расстановки скобок в строке
Что проверяют
Знаете ли вы, что задача решается стеком, и умеете ли аккуратно закрыть граничные случаи. На фронтенде это не абстракция: на стеке работает разбор шаблонов, проверка парности тегов и любые подсветки редактора, поэтому вопрос считается базовым.
Как отвечать
Объясните идею до кода: открывающая скобка кладётся на стек, закрывающая обязана совпасть с вершиной. Если совпала, вершина снимается, если нет или стек пуст, строка невалидна. В конце стек должен оказаться пустым.
function isValid(s) {
const pairs = { ")": "(", "]": "[", "}": "{" };
const stack = [];
for (const ch of s) {
if (ch === "(" || ch === "[" || ch === "{") {
stack.push(ch);
} else if (ch in pairs) {
if (stack.pop() !== pairs[ch]) return false;
}
}
return stack.length === 0;
}Назовите сложность сами: один проход, O(n) по времени и O(n) по памяти в худшем случае, когда вся строка состоит из открывающих скобок. Уточните у интервьюера, могут ли встречаться прочие символы: в решении выше они просто игнорируются, и это осознанное решение, а не случайность. Хорошее продолжение разговора: как задача меняется, если добавить кавычки и экранирование, где пара определяется не типом символа, а контекстом.
Где спотыкаются
Кладут на стек всё подряд. Ветка «иначе положить в стек» выглядит короче, но тогда буква между скобками попадает на вершину, и строка вида (a) объявляется невалидной, хотя автор уверен в обратном. Класть надо только открывающие скобки, проверяя их явным списком.
Не проверяют пустой стек при закрывающей скобке и остаток в конце. Строка ) при снятии с пустого стека даст undefined, а строка ( пройдёт цикл без единой ошибки. Обе проверки обязательны, и именно на них строятся тесты интервьюера.
Пытаются обойтись счётчиком или регулярным выражением. Счётчик не отличит ([)] от ()[], потому что порядок закрытия он не хранит, а регулярные выражения не умеют произвольную вложенность. Это тот случай, когда попытка быть остроумнее задачи стоит оффера.