PythonでK個の最大合計ペアを見つけるプログラム
問題の概要
2つの数値リスト nums0 と nums1、および整数 k が与えられたとします。目標は、nums0 の要素1つと nums1 の要素1つから構成されるペアの中から、合計値が大きい方から k 個のペアを見つけ出し、それらの合計を返すことです。
例えば、入力が nums1 = [8, 6, 12]、nums2 = [4, 6, 8]、k = 2 の場合、出力は 38 になります。これは、最大のペアが [12, 8](合計20)と [12, 6](合計18)であり、20 + 18 = 38 となるためです。
解法のアプローチ
この問題は、ヒープ(優先度付きキュー)を使うことで効率的に解けます。全てのペアの組み合わせを生成すると計算量が膨大になりますが、大きな合計を持つペアから順番に取り出すことで、必要な分だけ処理できます。具体的な手順は以下の通りです。
k > len(nums0) * len(nums1)の場合(作成可能なペアの総数より多く要求された場合)、0を返します。- 最小ヒープ
pqを新しく作成します。 - 答えを格納する変数
ansを0で初期化します。 nums0とnums1をそれぞれ昇順にソートします。i, jを、それぞれ両リストの末尾のインデックス(サイズ − 1)に設定します。- 訪問済みのインデックス組み合わせを記録するためのセット
visitedを作成します。 - ヒープ
pqに(−(nums0[i] + nums1[j]), i, j)をプッシュします。 - 0から
k回までループを実行し、以下の処理を行います。- ヒープ
pqからsum, i, jをポップします。 x := nums0[i − 1] + nums1[j]を計算します。(i − 1, j)がvisitedに存在しない場合は、visitedに追加し、ヒープに(−x, i − 1, j)をプッシュします。y := nums0[i] + nums1[j − 1]を計算します。(i, j − 1)がvisitedに存在しない場合は、visitedに追加し、ヒープに(−y, i, j − 1)をプッシュします。ans := ans + (−sum)として答えを累積します。
- ヒープ
- 最後に
ansを返します。
アルゴリズムのポイント
この手法の鍵となるのは、次の2点です。
- 負の値による最大ヒープのシミュレーション: Pythonの
heapqモジュールは最小ヒープしか提供していません。そこで、合計値にマイナスを付けて格納することで、最小ヒープを最大ヒープとして振る舞わせています。 - 隣接ペアへの段階的な展開: ソート済みリストの末尾同士のペアが最大の合計となります。ヒープからペアを取り出すたびに、「片方のリストのインデックスを1つ左にずらした隣接ペア」だけを候補として追加します。
visitedセットで重複を防ぐことで、無駄な計算を避けています。
これにより、全ペアを生成することなく、上位 k 個のペアだけを効率よく求められます。
Pythonでの実装例
理解を深めるために、以下の実装を見てみましょう。
from heapq import heappush, heappop
class Solution:
def solve(self, nums0, nums1, k):
if k > len(nums0) * len(nums1):
return 0
pq = []
ans = 0
nums0.sort(), nums1.sort()
i, j = len(nums0) - 1, len(nums1) - 1
visited = set()
heappush(pq, (-(nums0[i] + nums1[j]), i, j))
for _ in range(k):
sum, i, j = heappop(pq)
x = nums0[i - 1] + nums1[j]
if not (i - 1, j) in visited:
visited.add((i - 1, j))
heappush(pq, (-x, i - 1, j))
y = nums0[i] + nums1[j - 1]
if not (i, j - 1) in visited:
visited.add((i, j - 1))
heappush(pq, (-y, i, j - 1))
ans += -sum
return ans
ob = Solution()
print(ob.solve([8, 6, 12], [4, 6, 8], 2))
入力
[8, 6, 12],[4, 6, 8],2
出力
38
-
Pythonで配列(リスト)の合計を求める方法をわかりやすく解説
この記事では、配列(リスト)の合計値を求めるという問題に対して、Pythonでの解決策とアプローチをわかりやすく解説します。 問題の定義 配列が入力として与えられたとき、その配列に含まれるすべての要素の合計を計算することを目標とします。 例えば、[1, 2, 3, 4, 5] という配列が与えられた場合、出力は 15 になります。 アプローチ1:ループを使った素朴な方法(総当たり法) 最も基本的な方法は、リストを先頭から順に走査し、各要素を合計用の変数に加算していくやり方です。手順は以下の通りです。 合計を格納する変数を 0 で初期化します。 for ループでリストの各要素を取り出し、順番に
-
Pythonでリスト内のすべてのペア間の絶対差の合計を求めるプログラム
本記事では、リスト内のすべてのペア間の絶対差の合計を求める問題の解法とアプローチについて解説します。 問題文 リストが入力として与えられたとき、そのリスト内のすべてのペア間の絶対差の合計を求める必要があります。 解法のアプローチ enumerate() メソッドは、イテラブル(反復可能オブジェクト)にカウンターを付加し、enumerate オブジェクトとして返す組み込み関数です。ループ処理の中でインデックスと要素を同時に取得したい場合に非常に便利です。 この手法では、まず絶対差を格納するためのリスト「diffs」を用意します。 次に、2つの変数を持つ二重ループを使用します。片方はカウンター(イ