バックトラックで正しく閉じた括弧の並びを全部作る

n 組の丸括弧で作れる、正しく閉じた並びを全部、辞書の順で作ります。開き括弧はあと何個置けるか、閉じ括弧は開いた数を越えないか、の 2 つの決まりで枝を切りながら 1 文字ずつ伸ばす、バックトラックの練習です。

海外で定番の問題リスト 4 本には入っていません

問題

整数 n を受け取ります。開き括弧 ( を n 個と閉じ括弧 ) を n 個使ってできる、正しく閉じた並びを全部作り、文字列の並びで返す関数を書いてください。

  • 正しく閉じた並びとは、左から読んでいくどの時点でも、閉じ括弧の数が開き括弧の数を越えず、最後に両方の数が同じになる並びです。"(())" や "()()" は正しく、")(" や "())(" は正しくありません
  • 返す並びは、( を ) より前の文字と見た辞書の順にします。同じ並びを 2 回入れません
  • n は 1 以上 8 以下です

入力と出力の例

例 1

2 組では、入れ子の "(())" と、並べた "()()" の 2 つです。2 文字目が ( の方が先に来ます。

n = 2
["(())", "()()"]

例 2

1 組では、"()" の 1 つだけです。

n = 1
["()"]

例 3

3 組では 5 つです。辞書の順なので、( が前に多く続く物から並びます。

n = 3
["((()))", "(()())", "(())()", "()(())", "()()()"]

面接での聞かれ方

面接では、短い言葉で渡されることがよくあります。

  • 「n 組の括弧で作れる、正しい組み合わせを全部列挙してください」
  • 「返す順は決まっていますか?」と、自分から確かめるかを見られます
  • 書き終えたあとに「いくつ作られますか?」と、数の伸び方を聞かれることもあります

括弧の対応を確かめる問題 (スタックで判定する問題) と組で出されることがあります。判定ではなく作る問題なので、作る途中で正しくない並びに入らないように枝を切るのが要点です。

ヒント

まだ開いていません

付箋は 4 枚。下の段ほど答えに近づきます

  1. ヒント 2

  2. ヒント 3

  3. ヒント 4答えに近い

アルゴリズムのチートシートの「再帰と木」に、この型の要点を表とコードでまとめています。

再帰は、同じ形の小さい問題に分けて自分を呼ぶ書き方です。木の深さや、全部の組み合わせを数える問題で使います。

main.py
def gen_brackets(n: int) -> list[str]:
    """
    Goal: 何を返すか

    idea1: まず思いつく案
    -> runtime: O(?)  space: O(?)

    idea2: もっと速い案
    -> runtime: O(?)  space: O(?)

    edge case: 空、1 つだけ、など
    """
    # ここに書きます
    pass


# 「実行」を押すと、この行の結果が出ます
print(gen_brackets(2))

できているか「例で確かめる」を押すと、問題の例を全部この関数に渡して、通ったかをここに出します