← Назад к вопросам

Проверка скобок в выражении

1.7 Middle🔥 191 комментариев
#Теория тестирования

Условие

Напишите функцию, которая проверяет корректность расстановки скобок в математическом выражении.

Пример

Вход: (1 + 2) * (3 + 4) Выход: true

Вход: ((1 + 2) * 3 Выход: false

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Решение

Понимание задачи

Проверить, что все скобки в выражении расставлены корректно. Для этого нужно:

  • Каждой открывающей скобке соответствует закрывающая
  • Порядок соответствия правильный (нет пересечений)
  • Поддерживать три типа скобок: (), [], {}

Оптимальный алгоритм: Stack

def is_valid_parentheses(s):
    stack = []
    mapping = {')': '(', ']': '[', '}': '{'}
    
    for char in s:
        if char in mapping:
            # Закрывающая скобка
            if not stack or stack[-1] != mapping[char]:
                return False
            stack.pop()
        elif char in mapping.values():
            # Открывающая скобка
            stack.append(char)
    
    # Stack должен быть пустой
    return len(stack) == 0

Как это работает

Пример 1: (1 + 2) * (3 + 4)

Шаг 1: Видим '(' -> добавляем в stack: ['('] Шаг 2: Видим ')' -> проверяем top: '(' совпадает, удаляем: [] Шаг 3: Видим '(' -> добавляем: ['('] Шаг 4: Видим ')' -> совпадает, удаляем: [] Результат: stack пустой -> True

Пример 2: ((1 + 2) * 3

Шаг 1: '(' -> stack: ['('] Шаг 2: '(' -> stack: ['(', '('] Шаг 3: ')' -> совпадает, stack: ['('] Конец строки -> stack не пустой -> False

Сложность

  • Временная: O(n) — каждый символ посещаем один раз
  • Пространственная: O(n) — в худшем случае все открывающие скобки

Расширенная версия с поддержкой всех типов скобок

def is_valid_all_brackets(s):
    """
    Проверяет корректность всех типов скобок: (), [], {}
    """
    stack = []
    pairs = {')': '(', ']': '[', '}': '{'}
    
    for char in s:
        if char in pairs:
            # Закрывающая скобка
            if not stack or stack[-1] != pairs[char]:
                return False
            stack.pop()
        elif char in pairs.values():
            # Открывающая скобка
            stack.append(char)
    
    return len(stack) == 0

Тестирование

# Валидные выражения
assert is_valid_parentheses("()") == True
assert is_valid_parentheses("([])") == True
assert is_valid_parentheses("()[]{}") == True
assert is_valid_parentheses("(1 + 2) * (3 + 4)") == True
assert is_valid_parentheses("") == True

# Невалидные выражения
assert is_valid_parentheses("(") == False
assert is_valid_parentheses(")") == False
assert is_valid_parentheses("(()") == False
assert is_valid_parentheses("((1 + 2) * 3") == False
assert is_valid_parentheses("([)]") == False
assert is_valid_parentheses("([)][") == False

Альтернативные подходы

Способ 1: Счётчик (только одного типа скобок)

def is_valid_simple_count(s):
    count = 0
    for char in s:
        if char == '(':
            count += 1
        elif char == ')':
            count -= 1
            if count < 0:
                return False
    return count == 0
  • O(n) время, O(1) память
  • Работает только для одного типа скобок
  • Не ловит пересечение скобок

Способ 2: Регулярные выражения (менее эффективно)

import re

def is_valid_regex(s):
    while '()' in s or '[]' in s or '{}' in s:
        s = s.replace('()', '').replace('[]', '').replace('{}', '')
    return s == ''
  • O(n²) время в худшем случае
  • Менее эффективно

Граничные случаи

# Пустая строка - валидна
assert is_valid_parentheses("") == True

# Только открывающие скобки
assert is_valid_parentheses("(((") == False

# Только закрывающие скобки
assert is_valid_parentheses(")))") == False

# Смешанные типы с пересечениями
assert is_valid_parentheses("([)]") == False
assert is_valid_parentheses("{[}]") == False

# Вложенные скобки
assert is_valid_parentheses("[[[[]]]]" ) == True

Выводы

  • Stack — идеальная структура для этой задачи
  • O(n) время, O(n) память — оптимальная сложность
  • Работает для всех типов скобок — легко расширяется
  • Для QA: проверить граничные случаи, смешанные скобки, пересечения