2つのソートされたリストA(サイズm)とB(サイズn)を示します。
アルゴリズム:
- すべてのi=0からn-1についてA[0]とB[i]の合計を計算します。リストAから合計に含まれる要素を特定する必要があります。1つの方法は、インデックスを添付することです(すべての合計で0です)。ここ)。すべてのペアを、合計順に並べられた最小ヒープにプッシュします。
- ヒープをポップし、合計を取り出します。添付のインデックスを使用して、リストAの次の要素との合計を計算します。インデックスがすでにm-1の場合は、何もする必要はありません。それ以外の場合は、インデックスをインクリメントしてヒープにプッシュバックします。
- ヒープが空になるまで(すべてのm * n値に対して)ステップ2を繰り返します。
ステップ1はO(n log n)になります。
ステップ2は、ヒープのサイズが減少し、決して増加しない可能性があるため、最大でO(log n)です。ステップ2をm*n回繰り返すと、O(mn log n)の時間計算量になります。
全体的な複雑さはO(mn log n)です。
上記のアルゴリズムでリストBとして小さいリストを使用することにより、時間計算量をわずかに改善できます(大きなヒープではなく、小さなヒープを管理するだけで済みます)。
std::priority_queue
(Stackerによる)を使用した実装:
#include <iostream>
#include <set>
#include <queue>
#include <limits>
std::multiset<int> set1 {4, 8, 19, 25, 25, 26};
std::multiset<int> set2 {1, 2, 3, 8, 20, 27};
struct Node
{
Node(std::multiset<int>::const_iterator set1Iterator, int set2Value) :
set1Iterator(set1Iterator),
set2Value(set2Value),
sum(*set1Iterator + set2Value)
{
}
bool operator < (const Node& other) const
{
return sum > other.sum; // Reverse order as std::priority_queue sorts for the greatest value
}
std::multiset<int>::const_iterator set1Iterator;
int set2Value;
int sum;
};
int main()
{
std::priority_queue<Node> heap;
for (auto i = set2.begin(); i != set2.end(); ++i)
heap.push(Node(set1.begin(), *i));
while (!heap.empty())
{
Node min(heap.top());
heap.pop();
std::cout << *min.set1Iterator << " + " << min.set2Value << " = " <<
min.sum << std::endl;
if (++min.set1Iterator != set1.end())
{
min.sum = *min.set1Iterator + min.set2Value;
heap.push(min);
}
}
return 0;
}