Ich bin an einem effizienten Algorithmus interessiert Führen Sie die folgende Aufgabe aus:Wählen Sie Mengen von Zahlen {1,2,3} aus einer Reihe von Mengen {{..}, {..}, {..}} so dass alle Elemente eindeutig sind
- Ich habe eine Reihe von Sets, die jeweils aus drei Nummern bestehen.
- Innerhalb einer solchen Teilmenge sind die Nummern eindeutig.
- Sie können jedoch mehrmals in anderen Teilmengen auftreten.
- Das Ziel ist, z.B. 3 Teilmengen, so dass die Elemente nur einmal vorkommen.
Zum Beispiel: {{1,2,3}, {3,4,5}, {6,7,8}, {5,7,9}}
- die zweite Teilmenge hat 3 gemeinsam mit der ersten Teilmenge.
- Die vierte Teilmenge hat ein Element mit der zweiten und dritten Teilmenge gemeinsam.
- Wenn jetzt eine Anzahl von Teilmengen ausgewählt wird, kann das nicht sein. Jedes Element kann nur einmal vorkommen.
Ich implementierte etwas, das den Job erledigt, aber ich denke, dass kann effizienter durchgeführt werden. Wie? vielleicht gibt es sogar einen Konstant-Zeit-Algorithmus mit map
s oder so?
- Ich benutzte einen
list
den Satz für die Implementierung, weil ich gepflückt entfernen oder ausgeschlossen Subsets (schnell entfernen). - Subsets werden unter Verwendung von
vector
s implementiert. - Um bereits gewählte Nummern zu verfolgen, verwende ich eine
set
.
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <iterator>
#include <algorithm>
#include <random>
using namespace std;
random_device rd;
mt19937 rng(rd());
// pickes a random entry from a vector and returns an iterator to that element.
list<vector<int>>::iterator randomEntry(list< vector<int> >& v)
{
uniform_int_distribution<int> dis(0, v.size()-1); // guaranteed unbiased
auto it{ begin(v) };
advance(it, dis(rng));
return it;
}
int main()
{
// a collection of possible sets
list< vector<int> > collection;
collection.emplace_back(vector<int>{51,9,22});
collection.emplace_back(vector<int>{11,5,74});
collection.emplace_back(vector<int>{61,9,35}); // 2nd element in common with 1st entry
collection.emplace_back(vector<int>{19,54,66});
collection.emplace_back(vector<int>{53,86,35}); // 3rd element in common with 3rd entry
collection.emplace_back(vector<int>{11,3,55}); // 1st element in common with 2nd entry
// pick three -independent- sets form the collection
vector< vector<int> > picked;
set<int> elements;
while(picked.size()<3)
{
auto entry{ randomEntry(collection) }; // iterator to a randomly choosen entry
bool unused{ true };
for(const auto i : *entry)
{
if(elements.find(i) != cend(elements)) // if it already exists in elements, its already used.
unused= false;
}
if(unused)
picked.emplace_back(*entry);
collection.erase(entry); // in any chase, remove == don't pick it again.
}
// all the elements printed should only appear once.
for(const auto& i : collection)
{
for(const auto j : i)
cout<<j<<" ";
cout<<endl;
}
return 0;
}
Wenn Ihr Code funktioniert und Sie nur nach Verbesserungen suchen, sollten Sie dies auf http://codereview.stackexchange.com/ veröffentlichen. – MrSmith42