我有 3 套 A、B、C。我需要找到 联合(交集(A,B),交集(B,C),交集(A,C))
(A ∩ B) ∪ (B ∩ C) ∪ (A ∩ C) 集合表示法。
是否可以将其转换为代码而无需再声明 4 个集合。
#include <set>
using namespace std;
set<int> set1, set2, set3;
set1.insert(1);
set1.insert(2);
set2.insert(2);
set2.insert(3);
set3.insert(1);
set3.insert(4);
// set1 = {1,2} , set2 = {2,3}, set3 = {1,4}
这里是使用 set_intersection() 和 set_union() 的正常方法
set<int> res1, res2,res3;
set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), inserter(res1,res1.begin()));
set_intersection(set2.begin(), set2.end(), set3.begin(), set3.end(), inserter(res2,res2.begin()));
set_intersection(set1.begin(), set1.end(), set3.begin(), set3.end(), inserter(res3,res3.begin()));
set<int> result;
set_union(res1.begin(), res1.end(), res2.begin(), res2.end(), inserter(result, result.begin())
.
.
.
我想知道是否有更优雅的方法来代替。有人能给我一些建议吗?
答案 0 :(得分:1)
你可以,但这会是一个非常长的行,会惹怒任何试图阅读它的人。
至于更“优雅”的方法,您应该将您想要做的事情拆分成函数:
vector <int> getIntersection(vector < vector <int> > &sets)
{
vector <int> result; // To store the reaultant set
int smallSetInd = 0; // Initialize index of smallest set
int minSize = sets[0].size(); // Initialize size of smallest set
// sort all the sets, and also find the smallest set
for (int i = 1 ; i < sets.size() ; i++)
{
// sort this set
sort(sets[i].begin(), sets[i].end());
// update minSize, if needed
if (minSize > sets[i].size())
{
minSize = sets[i].size();
smallSetInd = i;
}
}
map<int,int> elementsMap;
// Add all the elements of smallest set to a map, if already present,
// update the frequency
for (int i = 0; i < sets[smallSetInd].size(); i++)
{
if (elementsMap.find( sets[smallSetInd][i] ) == elementsMap.end())
elementsMap[ sets[smallSetInd][i] ] = 1;
else
elementsMap[ sets[smallSetInd][i] ]++;
}
// iterate through the map elements to see if they are present in
// remaining sets
map<int,int>::iterator it;
for (it = elementsMap.begin(); it != elementsMap.end(); ++it)
{
int elem = it->first;
int freq = it->second;
bool bFound = true;
// Iterate through all sets
for (int j = 0 ; j < sets.size() ; j++)
{
// If this set is not the smallest set, then do binary search in it
if (j != smallSetInd)
{
// If the element is found in this set, then find its frequency
if (binary_search( sets[j].begin(), sets[j].end(), elem ))
{
int lInd = lower_bound(sets[j].begin(), sets[j].end(), elem)
- sets[j].begin();
int rInd = upper_bound(sets[j].begin(), sets[j].end(), elem)
- sets[j].begin();
// Update the minimum frequency, if needed
if ((rInd - lInd) < freq)
freq = rInd - lInd;
}
// If the element is not present in any set, then no need
// to proceed for this element.
else
{
bFound = false;
break;
}
}
}
// If element was found in all sets, then add it to result 'freq' times
if (bFound)
{
for (int k = 0; k < freq; k++)
result.push_back(elem);
}
}
return result;
}
然后在您的主干道(或您需要到达路口的任何地方)执行以下操作:
vector < vector <int> > sets;
vector <int> set1;
set1.push_back(1);
set1.push_back(1);
set1.push_back(2);
set1.push_back(2);
set1.push_back(5);
sets.push_back(set1);
vector <int> set2;
set2.push_back(1);
set2.push_back(1);
set2.push_back(4);
set2.push_back(3);
set2.push_back(5);
set2.push_back(9);
sets.push_back(set2);
vector <int> set3;
set3.push_back(1);
set3.push_back(1);
set3.push_back(2);
set3.push_back(3);
set3.push_back(5);
set3.push_back(6);
sets.push_back(set3);
vector <int> r = getIntersection(sets);
现在你有了一个你输入的集合之间的交集向量。它可以是 3,也可以是 30,000,等等。
答案 1 :(得分:0)
要获得集合的所有交集的并集,看起来您只需要获取出现在两个或多个集合中的所有值。交集是两个集合包含相同值的地方,联合是出现在“两个”集合中的所有值的集合。因此,所有可能的交集的联合将包括出现在至少两个集合中的任何值。
例如,对于集合 {1, 2}
、{2, 3}
和 {1, 4}
,所有交集的并集将为 {1, 2}
。
这应该适用于任意数量的集合。
#include <iostream>
#include <unordered_map>
#include <set>
#include <vector>
std::set<int> unionOfIntersections(const std::vector<const std::set<int>*>& sets) {
std::unordered_map<int, int> flattened_value_count_map;
for (const auto& set : sets) {
for (const int num : *set) {
auto overlaps_iter = flattened_value_count_map.find(num);
// Count the number of times each value occurs, for every set
if (overlaps_iter == flattened_value_count_map.end()) {
flattened_value_count_map[num] = 1;
}
else {
++overlaps_iter->second;
}
}
}
std::set<int> unionResult;
// C++ 17+ required for destructuring
for (const auto [value, numSetsIn] : flattened_value_count_map) {
// Include value in the union if it is present in two or more sets
if (numSetsIn >= 2) {
unionResult.emplace(value);
}
}
return unionResult;
}
int main() {
std::set<int> set1, set2, set3, set4;
set1.emplace(1);
set1.emplace(2);
set2.emplace(2);
set2.emplace(3);
set3.emplace(1);
set3.emplace(4);
set4.emplace(4);
set4.emplace(5);
for (const int value : unionOfIntersections({&set1, &set2, &set3, &set4})) {
std::cout << value << '\n';
}
return EXIT_SUCCESS;
}