【Python】動的計画法で合計がkになる組み合わせの数を求める方法
重複のない整数のリスト nums と、ある数値 k が与えられたとき、要素の合計がちょうど k になる組み合わせが何通り存在するかを求めます。なお、組み合わせを作る際には、同じ数字を何度でも繰り返し使って構いません。
たとえば、入力が nums = [2, 4, 5]、k = 4 の場合、出力は 2 になります。[2, 2] と [4] の2通りの作り方が存在するためです。
解法のアプローチ(動的計画法)
この問題は、いわゆる「コイン両替問題」と同型で、動的計画法(DP)を使うことで効率的に解けます。考え方の手順は以下の通りです。
- サイズが k+1 のリスト
tableを用意し、すべて 0 で初期化する table[0] := 1とする(合計 0 を作る方法は「何も選ばない」の1通りだけ)numsの各numについて、以下を繰り返すiがnumからkまでの範囲で、table[i] := table[i] + table[i - num]を実行する
- 最後に
table[k]を返す
ここで重要なのは、数字ごとの外側ループ・合計額の内側ループという順序にすることです。この順序により「[2, 4] と [4, 2]」のような順列の重複が排除され、組み合わせだけが正しくカウントされます。
それでは、実際の実装を見てみましょう。
サンプルコード
class Solution:
def solve(self, nums, k):
table = [1] + [0] * k
for num in nums:
for i in range(num, k + 1):
table[i] += table[i - num]
return table[k]
ob = Solution()
nums = [2, 4, 5]
k = 4
print(ob.solve(nums, k))入力
[2, 4, 5], 4
出力
2
処理の流れを追ってみる
num = 2 を処理した時点で table は [1, 0, 1, 0, 1](2だけで作れる合計のパターン)となり、続いて num = 4 を処理すると table[4] に [4] 単体のパターンが加わって 2 になります。num = 5 は k = 4 より大きいため影響しません。
計算量
時間計算量は O(n × k)(n は nums の要素数)、空間計算量は O(k) です。全組み合わせを総当たりする指数時間の探索と比べ、非常に効率的に答えを求められます。
-
Pythonで数の偶数の約数の合計を求めるプログラムの実装方法
本記事では、以下の問題文に対する解決策について学びます。問題文整数 n が与えられたとき、その数の偶数の約数(偶因子)の合計を求めることが課題です。この問題を解くには、まず奇数の約数をすべて除外する必要があります。入力された数が奇数の場合、偶数の約数は一つも存在しないため、直接 0 を返します。そうでない場合は、以下のコードで示すアプローチに従います。アルゴリズムの考え方このアプローチでは素因数分解を活用します。約数の合計は「各素因数の冪乗の和の積」として表せるという性質を利用します。偶数の約数のみを対象とするため、素因数 2 の部分については 20(つまり 1)を除外し、21 以降の項だけを
-
Pythonで数の因子の最小合計を求めるプログラム|素因数分解の考え方
本記事では、与えられた整数について、積が元の数と等しくなる因子の組み合わせの中から合計が最小となる値を求める方法を、Pythonのコード例とともに解説します。 問題定義 入力として1つの整数が与えられます。この数を複数の因子の積として表したとき、因子の合計が最小になるケースを求めてください。 すべての因子の組み合わせを網羅的に調べて合計を比較する方法もありますが、実はもっとシンプルで効率的なアプローチが存在します。 考え方:素因数の合計が最小になる 鍵となるのは次の性質です。積が一定の値になるとき、因子の合計が最小になるのは、すべての因子を素数まで分解した場合(素因数分解した場合)です。