【Python】バックトラッキングで有効な括弧の組み合わせをすべて生成する方法
問題の概要
整数 n が与えられたとき、開き括弧「(」と閉じ括弧「)」がそれぞれ n 個ずつ含まれる、すべての正しく対応した括弧の組み合わせを生成することを考えます。
例えば n = 3 の場合、生成される括弧のセットは次のようになります。
["()()()", "()(())", "(())()", "(()())", "((()))"]
ここで「正しく対応した」とは、任意の時点で閉じ括弧の数が開き括弧の数を超えず、最終的にすべての括弧が対応関係を持つ状態を指します。この問題は LeetCode の「Generate Parentheses」でもおなじみの、バックトラッキングの代表的な例題です。
解決アプローチ
この問題は再帰(バックトラッキング)を用いて解きます。基本的なアイデアは以下の通りです。
generateParenthesisUtil()というメソッドを定義します。引数として、残りの開き括弧数left、残りの閉じ括弧数right、現在構築中の文字列temp、そして結果を格納する配列resultを受け取ります。初期状態ではresultは空です。- この関数は以下のように動作します。
left == 0かつright == 0の場合:すべての括弧を使い切ったため、完成した文字列tempをresultに追加して処理を終了します。left > 0の場合:開き括弧がまだ残っているので、「(」を追加して再帰呼び出しを行います。generateParenthesisUtil(left - 1, right, temp + "(", result)right > leftの場合:閉じ括弧の方が多く残っているときだけ「)」を追加できます(これにより、未対応の開き括弧が必ず存在することが保証されます)。generateParenthesisUtil(left, right - 1, temp + ")", result)
Pythonでの実装例
実際のコードを見てみましょう。
class Solution(object):
def generateParenthesis(self, n):
"""
:type n: int
:rtype: List[str]
"""
result = []
self.generateParenthesisUtil(n, n, "", result)
return result
def generateParenthesisUtil(self, left, right, temp, result):
if left == 0 and right == 0:
result.append(temp)
return
if left > 0:
self.generateParenthesisUtil(left - 1, right, temp + '(', result)
if right > left:
self.generateParenthesisUtil(left, right - 1, temp + ')', result)
ob = Solution()
print(ob.generateParenthesis(4))入力
4
出力
["(((())))", "((()()))", "((())())", "((()))()", "(()(()))", "(()()())", "(()())()", "(())(())", "(())()()", "()((()))", "()(()())", "()(())()", "()()(())", "()()()()"]
仕組みのポイント
このアルゴリズムの核心は条件式 right > left にあります。開き括弧を追加すると left が減り、閉じ括弧を追加すると right が減るため、「残りの閉じ括弧数 > 残りの開き括弧数」という状態は「文字列中にまだ閉じていない開き括弧が存在する」ことを意味します。この条件があることで、無効な文字列(例えば ")((" のようなもの)が生成されることを事前に防ぎ、探索木を大幅に枝刈りできます。
計算量についても触れておくと、有効な括弧の組み合わせの総数はカタラン数 C(2n, n) / (n + 1) で表され、時間計算量・空間計算量は O(4ⁿ / √n) 程度となります。
-
Pythonで二分木が平衡(バランス)しているか判定する方法
平衡二分木(Height-Balanced Binary Tree)とは? 二分木では、各ノードは最大2つの子、すなわち「左の子」と「右の子」を持ちます。ある二分木が与えられたとき、その木が平衡(バランス)しているかどうかを判定することは、データ構造とアルゴリズムの学習における重要なテーマの一つです。 定義: すべてのノードについて、左部分木と右部分木の高さの差が「1」以下である場合、その二分木は平衡(height-balanced)であるとみなされます。 例1:平衡しているケース 入力: 1 / \ 2 3 / \
-
PythonのpyqrcodeモジュールでQRコードを生成する方法
QRコードは、白い背景の上に黒い四角形を格子状に配置した2次元コードで、カメラなどの画像読み取り装置によって読み取ることができます。商業用途での在庫追跡や決済、ウェブサイトへのログインなど、スマートフォンユーザー向けのさまざまなアプリケーションで広く利用されています。Pythonではpyqrcodeモジュールを使うことで、簡単にQRコードを生成できます。QRコードには、データを効率的に格納するための4つの標準エンコードモード(数値モード、英数字モード、バイト/バイナリモード、漢字モード)が用意されています。英数字のQRコードを生成するpyqrcodeモジュールには、QRコードを生成するためのc