Как стать автором
Обновить

О генерации скобочных последовательностей

Время на прочтение2 мин
Количество просмотров6.5K

Всем доброго времени суток!

Эта коротенькая заметка посвящена симпатичной задачке генерации в лексикографическом порядке всех правильных скобочных последовательностей. Её нередко включают в список задач для подготовки к собеседованию (например, здесь).

По просторам инета гуляет следующее решение:

def  gen_parentheses(parentheses_count, str_, left, right, out_file):
    if left == parentheses_count and right == parentheses_count:
        out_file.write(str_ + "\n")
    return
    if left < parentheses_count:
        gen_parentheses(parentheses_count, str_ + "(", left + 1, right, out_file)
    if right < left:
        gen_parentheses(parentheses_count, str_ + ")", left, right + 1, out_file)

with open("input.txt") as in_file:
    parentheses_count = int(next(in_file))
with open("output.txt", "w") as out_file:
    gen_parentheses(parentheses_count, "", 0, 0, out_file)

Оно, несмотря на его изящную простоту, вызывало чувство некоторой неудовлетворённости :). Присмотревшись, я понял, чем был вызван мой творческий зуд :) –подсознательно не нравилось, что на добавление каждой скобки требовался отдельный вызов функции. Конечно, хотелось бы сократить глубину рекурсии. Сделать это оказалось совсем не сложно.

Ну, во-первых, очевидно, что если число добавленных открывающихся скобок достигло заданного, то нет смысла добавлять соответствующие закрывающиеся скобки по одной – можно сразу добавить все недостающие закрывающиеся скобки:

def  gen_parentheses_v1(parentheses_count, str_, left, right, out_file):
    if left < parentheses_count:
        gen_parentheses_v1(parentheses_count, str_ + "(", left + 1, right, out_file)
        if right < left:
            gen_parentheses_v1(parentheses_count, str_ + ")", left, right + 1, out_file)
    else:
        out_file.write(str_ + (parentheses_count-right)*")" + "\n")

А во-вторых, да и с открывающимися скобками можно не тормозить :) – добавлять не по одной, а сразу строкой из нескольких открывающихся скобок и одной закрывающейся:

def gen_parentheses_v2(parentheses_count, str_, left, right, out_file):
    if left < parentheses_count:
        for i in range(parentheses_count, max(left, right+1) - 1, -1):  
            gen_parentheses_v2(parentheses_count,
                               str_ + (i-left)*"(" + ")",
                               i,
                               right + 1,
                               out_file)
    else:
        out_file.write(str_ + (parentheses_count-right)*")" + "\n")

В итоге глубина рекурсии снизилась более чем в два раза :)

Теги:
Хабы:
Всего голосов 1: ↑1 и ↓0+1
Комментарии14

Публикации

Истории

Работа

Python разработчик
130 вакансий
Data Scientist
76 вакансий

Ближайшие события

7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
28 ноября
Конференция «TechRec: ITHR CAMPUS»
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань