Pythonでターゲットの合計となる4つの数の組み合わせを数えるプログラム
問題の概要
4つの数値リスト A、B、C、D とターゲット値が与えられたとき、A[i] + B[j] + C[k] + D[l] がターゲットと等しくなるような異なる組(i, j, k, l)の個数を求めることを考えます。
例えば、入力が以下のような場合を想定します。
- A = [5, 4, 3]
- B = [8, 4]
- C = [6, 2]
- D = [4, 10]
- target = 23
このとき出力は 3 となり、条件を満たす組は [5, 8, 6, 4]、[3, 4, 6, 10]、[3, 8, 2, 10] の3つです。
解法のアプローチ
すべての組み合わせを総当たりで調べると計算量が O(n⁴) となり、リストが大きくなると非常に非効率です。そこで、ハッシュマップを活用した効率的な手法を採用します。手順は以下の通りです。
- カウント変数 count を 0 で初期化する
- 空のマップ m を用意する
- A の各要素 i と B の各要素 j について、m[i + j] の値を1ずつ増やす
- C の各要素 k と D の各要素 z について、target − (k + z) が m に存在すれば、count に m[target − (k + z)] を加算する
- count を返す
この方法では、A と B のペアの和を事前にマップへ記録しておき、C と D のペアに対して「ターゲットに到達するために必要な残りの値」がマップに存在するかを確認します。これにより、計算量を O(n²) まで抑えることができます。
実装例
それでは、実際のコードを見てみましょう。
class Solution:
def solve(self, A, B, C, D, target):
count = 0
from collections import defaultdict
m = defaultdict(int)
for i in A:
for j in B:
m[i + j] += 1
for k in C:
for z in D:
if target - (k + z) in m:
count += m[target - (k + z)]
return count
ob = Solution()
A = [5, 4, 3]
B = [8, 4]
C = [6, 2]
D = [4, 10]
target = 23
print(ob.solve(A, B, C, D, target))入力
[5, 4, 3], [8, 4], [6, 2], [4, 10], 23
出力
3
まとめ
collections モジュールの defaultdict を使うことで、キーの存在チェックや初期化を簡潔に扱えます。ハッシュマップを活用することで、4つのリストからターゲットの合計となる組み合わせを効率的に数えられます。素朴な全探索では O(n⁴) かかるところを O(n²) に削減できるのが、この手法の大きな利点です。
-
Pythonで数の偶数の約数の合計を求めるプログラムの実装方法
本記事では、以下の問題文に対する解決策について学びます。問題文整数 n が与えられたとき、その数の偶数の約数(偶因子)の合計を求めることが課題です。この問題を解くには、まず奇数の約数をすべて除外する必要があります。入力された数が奇数の場合、偶数の約数は一つも存在しないため、直接 0 を返します。そうでない場合は、以下のコードで示すアプローチに従います。アルゴリズムの考え方このアプローチでは素因数分解を活用します。約数の合計は「各素因数の冪乗の和の積」として表せるという性質を利用します。偶数の約数のみを対象とするため、素因数 2 の部分については 20(つまり 1)を除外し、21 以降の項だけを
-
Pythonで数の因子の最小合計を求めるプログラム|素因数分解の考え方
本記事では、与えられた整数について、積が元の数と等しくなる因子の組み合わせの中から合計が最小となる値を求める方法を、Pythonのコード例とともに解説します。 問題定義 入力として1つの整数が与えられます。この数を複数の因子の積として表したとき、因子の合計が最小になるケースを求めてください。 すべての因子の組み合わせを網羅的に調べて合計を比較する方法もありますが、実はもっとシンプルで効率的なアプローチが存在します。 考え方:素因数の合計が最小になる 鍵となるのは次の性質です。積が一定の値になるとき、因子の合計が最小になるのは、すべての因子を素数まで分解した場合(素因数分解した場合)です。