Pythonで演算子と括弧を挿入して24を作れるかどうかを判定するプログラム
問題の概要
1から9の範囲にある数字が、固定された順序でリストとして与えられます。これらの数字の間に「+」「-」「*」「/」(/は整数除算を表す)の演算子を挿入し、さらに括弧でグループ化することで、計算結果を24にできるかどうかを判定するのがこの問題です。
例えば、入力が nums = [5, 3, 6, 8, 7] の場合、(5 * 3) - 6 + (8 + 7) = 24 となるため、出力は True になります。
解決のアプローチ
この問題は、再帰的な分割統治法を用いて効率的に解くことができます。数列を前半と後半に分割し、それぞれの部分で作り出せるすべての値を列挙して、それらを4種類の演算子で組み合わせます。具体的な手順は以下の通りです。
- 関数 recur() を定義する。引数として配列 arr を受け取る
- answer := 新しいリスト
- i を 0 から arr のサイズ - 2 まで繰り返す
- pre := recur(arr[先頭から i まで])
- suf := recur(arr[i + 1 から末尾まで])
- pre の各要素 k に対して
- suf の各要素 j に対して
- answer の末尾に (k + j) を追加
- answer の末尾に (k - j) を追加
- answer の末尾に (k * j) を追加
- j が 0 でない場合
- answer の末尾に (k / j の商) を追加
- suf の各要素 j に対して
- answer のサイズが 0 で、かつ arr のサイズが 1 の場合
- answer の末尾に arr[0] を追加
- answer を返す
- メイン処理では、24 が recur(nums) の結果に含まれているかを確認し、含まれていれば True、そうでなければ False を返す
この方法では、0による除算を回避するために、割り算の結果は j が 0 でない場合にのみ追加している点に注目してください。また、配列のサイズが1のとき(再帰の終端)には、その要素自体が唯一の候補値となります。
実装例
以下にPythonでの実装を示します。
class Solution:
def solve(self, nums):
def recur(arr):
answer = []
for i in range(len(arr) - 1):
pre, suf = recur(arr[: i + 1]), recur(arr[i + 1 :])
for k in pre:
for j in suf:
answer.append(k + j)
answer.append(k - j)
answer.append(k * j)
if j != 0:
answer.append(k // j)
if len(answer) == 0 and len(arr) == 1:
answer.append(arr[0])
return answer
return 24 in recur(nums)
ob = Solution()
nums = [5, 3, 6, 8, 7]
print(ob.solve(nums))
入力
[5, 3, 6, 8, 7]
出力
True
まとめ
このアルゴリズムは、すべての分割位置と演算子の組み合わせを再帰的に探索することで、24が作れるかどうかを確実に判定できます。計算量は数列の分割数と値の組み合わせ数に依存しますが、要素数が限られている場合は十分に実用的な速度で動作します。
-
Pythonで左右の部分木の入れ替えにより2つの二分木を一致させられるか判定する方法
問題の概要 2つの二分木が与えられたとき、任意のノードについて左部分木と右部分木を何度でも入れ替えてよいと仮定します。この操作を繰り返すことで、1つ目の木を2つ目の木とまったく同じ形に変換できるかどうかを判定するのが、この記事で扱う問題です。 例えば、次のような2つの木が入力として与えられた場合、左右の入れ替えによって一致させられるため、出力は True になります。 解決のアプローチ この問題は、幅優先探索(BFS)の考え方を使い、木をレベル(深さ)ごとに処理しながらノードの値を比較することで解けます。左右の入れ替えによって同じレベル内の値の並び順は反転し得るため、「順方向」または「逆方
-
【Python】リストの先頭(インデックス0)から最後の位置に到達できるか判定するプログラム
数値のリスト nums があるとします。各要素は、その位置から一度に進める最大ジャンプ数を表しています。このとき、インデックス0からスタートして、リストの最後のインデックスに到達できるかどうかを判定する必要があります。例えば、入力が nums = [2,5,0,2,0] の場合、出力は True になります。これは、インデックス0から1へジャンプし、さらにインデックス1(値が5なので最大5つ先まで進める)から最後のインデックスへ直接ジャンプできるためです。解法のアプローチこの問題は動的計画法(DP)を使って効率的に解くことができます。ポイントは、リストを後ろから前に向かって走査し、「その位置か