バックトラックで 正しく 閉じた 括弧の 並びを全部作る
n 組の
海外で定番の問題リスト 4 本には入っていません
問題
整数 n を( を n 個と) を n 個使って
- 正しく
閉じた 並びとは、 左から 読んでいくどの 時点でも、 閉じ括弧の 数が 開き括弧の 数を 越えず、 最後に 両方の 数が 同じに なる 並びです。 "(())"や"()()"は正しく、 ")("や"())("は正しく ありません - 返す
並びは、 (を)より前の 文字と 見た 辞書の 順にします。 同じ 並びを 2 回入れません nは 1 以上 8 以下です
入力と出力の例
例 1
2 組では、"(())" と、"()()" の 2 つです。( の
例 2
1 組では、"()" の 1 つだけです。
例 3
3 組では 5 つです。( が
面接での聞かれ方
面接では、
- 「n 組の
括弧で 作れる、 正しい 組み合わせを 全部 列挙してください」 - 「返す順は
決まっていますか?」と、 自分から 確かめるかを 見られます - 書き終えた
あとに 「いくつ作られますか?」と、 数の 伸び方を 聞かれる こともあります
括弧の
ヒント
まだ開いていません
付箋は 4 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3
ヒント 4答えに近い
アルゴリズムのチートシートの「再帰と木」に、
関わる学び
再帰は、
まず 考える手順
段 1
素直に( と ) を 2n 文字並べる 2 の 2n 乗通りを
段 2
1 文字ずつ右へ( を) を( は、n より) は、( の
段 3
長さが 2n に( を) を( を
段 4
持つ値を) の( の( のo の 2 つで) を) のo」は、o」と
解答
Python
Python
def gen_brackets(n):
out = []
def grow(s, o):
if len(s) == 2 * n:
out.append(s)
return
if o < n:
grow(s + "(", o + 1)
if len(s) < 2 * o:
grow(s + ")", o)
grow("", 0)
return outJavaScript
JavaScript
function genBrackets(
n
) {
const out = [];
const grow = (s, o) => {
if (s.length === 2 * n) {
out.push(s);
return;
}
if (o < n) {
grow(s + "(", o + 1);
}
if (s.length < 2 * o) {
grow(s + ")", o);
}
};
grow("", 0);
return out;
}Go
Go
func genBrackets(
n int,
) []string {
out := []string{}
var grow func(s string, o int)
grow = func(s string, o int) {
if len(s) == 2*n {
out = append(out, s)
return
}
if o < n {
grow(s+"(", o+1)
}
if len(s) < 2*o {
grow(s+")", o)
}
}
grow("", 0)
return out
}grow は、s と、( のo をs + "(" はvar grow で
計算量
- 作られる
並びの 数は、 カタラン数と 呼ばれる 数です。 n が 1 から 8 で、 1、 2、 5、 14、 42、 132、 429、 1430 と 伸びます。 おおよそ 4 の n 乗を n の 1.5 乗で 割った 速さで増えます - 時間は、
並びの 数 × 2n ほどです。 正しくなる 手前でしか 伸ばさないので、 途中で 捨てる 枝が ありません。 並び 1 つを 作るのに、 長さ 2n の 文字列を 作る 手間が かかります - 使う
記憶は、 答えを 除けば O(n) です。 呼び出しの 深さが 2n までです - 段 1 の
全部作って 確かめる 書き方は、 2 の 2n 乗 × 2n ほどの手間です
よく ある間違い
)を置ける 条件を 「 )の数 < n」にする。"())("のような、途中で 閉じすぎる 並びまで 作ってしまいます。 比べる 相手は nではなく、いま開いている (の数です)を先に試す。 正しい 並びは 全部作れますが、 順が 辞書の 順の 逆に なり、 例 1 で ["()()", "(())"]を返します。 (を先に試します - 長さが 2n に
なった ときに、 正しいかを もう 一度確かめる。 決まりを 守って 伸ばしたので、 必ず正しくなっています。 確かめは 要りません - 並びを 1 つの
配列に 足し 引きして 作り、 答えに 配列を そのまま入れる。 あとで 書き換わった 同じ 配列を 何度も 入れる ことになります。 入れる ときに 文字列に 直すか、 毎回新しい 文字列を作ります
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「1 文字ずつ
伸ばし、 正しくなくなる 手前で 止める バックトラックで 書きます。 開き括弧は、 使った 数が n より 少なければ 置けます。 閉じ括弧は、 使った 数が 開き括弧の 数より 少なければ 置けます。 長さが 2n に なったら 答えに 足します。 開き括弧を 先に 試すので、 辞書の 順に 作られます。 作る 数は カタラン数で、 捨てる枝は ありません。」
書き終えたら、
「例 1 で
たどります。 空から (を置きます。 開きは 1 で n の 2 より 少ないので、 もう 1 つ (を置いて ((。開きは 2 で 上限なので )を 2 回置き、(())を足します。 戻って、 (の次に )を置いて ()。また (と)を置いて ()()を足します。」