假设我有两组数据,每个条目都包含一个权重。每组按重量递增排序。我将列出几个示例集:
Set 0: {4, 8, 19, 25, 25, 26}
Set 1: {1, 2, 3, 8, 20, 27}
我想找到这两组之间的所有可能的对,但我想按照从最小到最大的总重量的顺序找到这些对。所以4 + 1,4 + 2,4 + 3,4 + 1等你可以假设这些集合是c ++ std::multiset
,但除此之外,我认为它在任何语言中都是相同的。
现在,我考虑过有2个迭代器,并按顺序从第一个与每个第二个配对开始迭代,但不会从最小的总和权重开始按顺序计算每个对,因为Set 0: 4
+ Set 1: 8
>在此示例中,Set 0: 8
+ Set 1: 1
。我总是可以将结果转储到一个为我做排序的容器中,但这似乎效率低下。我还有其他一些优化,这些优化也取决于能否做到这一点。有没有一种聪明的方法来做到这一点,最后没有额外的排序?
编辑:我需要获得所有可能的配对,因此它不像递增一个迭代器那样简单,也不是为了获得最小的总和。这将错过大多数(一半?)的对。虽然可能有某种迭代器堆栈......
答案 0 :(得分:2)
#include <iostream>
#include <set>
#include <vector>
#include <limits>
std::multiset<int> set1 {4, 8, 19, 25, 25, 26};
std::multiset<int> set2 {1, 2, 3, 8, 20, 27};
int main()
{
std::vector<std::pair<std::multiset<int>::const_iterator,
std::multiset<int>::const_iterator>> setIterators;
for (auto i = set1.begin(); i != set1.end(); ++i)
setIterators.push_back(std::make_pair(i, set2.begin()));
for (std::size_t count = set1.size() * set2.size(); count != 0; --count)
{
int minValue = std::numeric_limits<int>::max();
auto minElement = setIterators.begin();
for (auto i = setIterators.begin(); i != setIterators.end(); ++i)
{
if (i->second == set2.end())
continue;
int sum = *i->first + *i->second;
if (sum < minValue)
{
minValue = sum;
minElement = i;
}
}
std::cout << *minElement->first << " + " << *minElement->second << " = " <<
minValue << std::endl;
++minElement->second;
}
return 0;
}
输出:
$ g++ -std=c++11 main.cpp -o main && ./main
4 + 1 = 5
4 + 2 = 6
4 + 3 = 7
8 + 1 = 9
8 + 2 = 10
8 + 3 = 11
4 + 8 = 12
...
26 + 27 = 53
答案 1 :(得分:2)
让我们表示2个排序列表A(大小m)和B(大小n)。
算法:
步骤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;
}