プレフィックスとサフィックスの全位置でBの数がA以上となる文字列の並べ方を求めるPythonプログラム
問題の概要
「A」がn個、「B」が2n個含まれる文字列を考えます。このとき、文字列のすべての接頭辞(プレフィックス)とすべての接尾辞(サフィックス)を取り出しても、「B」の数が常に「A」の数以上になっているような並べ方が何通り存在するかを求めるのが本記事のテーマです。
例えば、n = 2 の場合を考えてみましょう。「A」が2個、「B」が4個あるとき、条件を満たす並べ方は次の4通りになります。
- BBAABB
- BABABB
- BBABAB
- BABBAB
したがって、入力が n = 2 のとき、出力は 4 となります。
解法のアプローチ
この問題は、再帰呼び出しを利用した分割統治の考え方で解くことができます。手順は以下の通りです。
- 引数として n を受け取るメソッド
solveを定義します。 - n が 1 の場合は、1 を返します。
- n が 2 の場合は、4 を返します。
- n が奇数の場合は、
solve((n-1)//2)の2乗を返します。 - n が偶数の場合は、
solve(n//2)の2乗を返します。
Pythonでの実装例
それでは、上記の手順を実際のコードで確認してみましょう。
def solve(n):
if n == 1:
return 1
if n == 2:
return 4
if n % 2 != 0:
return solve((n - 1) // 2) ** 2
else:
return solve(n // 2) ** 2
n = 2
print(solve(n))
実行結果
入力:
2
出力:
4
コードのポイント
この実装では、まず n = 1 と n = 2 の場合をベースケースとして扱い、それぞれ既知の答えである 1 と 4 を直接返しています。それより大きい n に対しては、n の偶奇に応じて問題を半分のサイズの部分問題へと帰着させ、再帰的に解いた結果を2乗することで最終的な答えを導いています。
このように再帰構造を活かすことで、すべての並べ方を網羅的に列挙することなく、答えをコンパクトに計算できる点がこのアプローチの特徴です。
-
Pythonでn個のルークが互いに攻撃し合わないように配置する方法の数を求めるプログラム
この記事では、n×n のチェス盤に n 個のルークを、互いに攻撃し合わないように配置する方法が何通りあるかを Python で求める方法を解説します。 問題の概要 サイズ n×n のチェス盤があるとします。ここに n 個のルークを、どのルークも他のルークを攻撃できないように配置するとき、その配置方法の総数を求めます。 ルークは同じ行または同じ列にある駒を攻撃できるため、「互いに攻撃し合わない」という条件は「すべてのルークがそれぞれ異なる行・異なる列に存在する」ことを意味します。 また、2つの配置方法は、あるマスが一方の配置では占められていて、もう一方では占められていない場合に「異なる」とみな
-
PythonでS1の接頭辞とS2の接尾辞を連結すると回文になるインデックスiを見つける方法
問題概要同じ長さを持つ2つの文字列S1とS2が与えられたとき、S1[0…i]とS2[i+1…n-1]を連結した結果が回文になるようなインデックスiを見つけます。そのようなインデックスが存在しない場合は、-1を返します。例えば、入力がS1 = pqrsu、S2 = wxyqpである場合を考えてみましょう。このとき出力は1になります。なぜなら、S1[0..1] = pq、S2[2..n-1] = ypqであり、これらを連結したpqyqpは回文になるためです。解法のアプローチこの問題を解くためには、以下の手順に従います。nにstr1のサイズ(長さ)を代入します空文字列strを用意しますiを0からnま