it-swarm.com.de

Effizienter Listenschnittalgorithmus

Welcher Algorithmus ist bei zwei nicht unbedingt sortierten Listen am effizientesten, um die Schnittmenge dieser Listen zu finden?

71
David

Sie können alle Elemente der ersten Liste in ein Hash-Set einfügen. Dann iterieren Sie den zweiten und überprüfen für jedes seiner Elemente den Hash, um festzustellen, ob er in der ersten Liste vorhanden ist. Wenn ja, geben Sie es als Element der Schnittmenge aus.

34
Frank

Vielleicht möchten Sie einen Blick auf Bloom-Filter werfen. Sie sind Bitvektoren, die eine probabilistische Antwort darauf geben, ob ein Element Mitglied einer Menge ist. Schnittmenge setzen kann mit einer einfachen bitweisen UND-Verknüpfung realisiert werden. Wenn Sie eine große Anzahl von Nulldurchschnitten haben, können Sie diese mithilfe des Bloom-Filters schnell entfernen. Sie müssen jedoch immer noch auf einen der anderen hier genannten Algorithmen zurückgreifen, um die tatsächliche Schnittmenge zu berechnen. http://en.wikipedia.org/wiki/Bloom_filter

21

ich nehme an, Sie haben ohne Hash zwei Möglichkeiten:

  • Der naive Weg wird sein, jedes Element mit jedem anderen Element zu vergleichen. O (n ^ 2)
  • Eine andere Möglichkeit wäre, die Listen zuerst zu sortieren und sie dann zu durchlaufen: O (n lg n) * 2 + 2 * O (n)
9
Tom Ritter

Aus der eviews features list geht hervor, dass sie komplexe Zusammenführungen und Verknüpfungen unterstützt (wenn dies wie in der DB-Terminologie "Verknüpfung" ist, wird eine Schnittmenge berechnet). Stöbern Sie jetzt in Ihrer Dokumentation :-)

Zusätzlich hat eviews ein eigenes Benutzerforum - warum nicht dort fragen?

7
zvrba

mit set 1 baue einen binären Suchbaum mit O(log n) und iteriere set2 und suche die BST m X O(log n) so total O(log n) + O(m)+O(log n) ==> O(log n)(m+1)

6
khaja

in C++ kann Folgendes mit der STL-Map versucht werden

vector<int> set_intersection(vector<int> s1, vector<int> s2){

    vector<int> ret;
    map<int, bool> store;
    for(int i=0; i < s1.size(); i++){

        store[s1[i]] = true;
    }
    for(int i=0; i < s2.size(); i++){

        if(store[s2[i]] == true) ret.Push_back(s2[i]);

    }
    return ret;
}
6
quasar

Hier ist eine andere mögliche Lösung, die ich mir ausgedacht habe: O(nlogn) in zeitlicher Komplexität und ohne zusätzlichen Speicher. Sie können sie hier nachlesen https: //Gist.github). com/445537

So funktioniert es: Unter der Annahme, dass die Sätze keine Wiederholung enthalten, führen Sie alle Sätze zu einem zusammen und sortieren Sie sie. Durchlaufen Sie dann die zusammengeführte Menge und erstellen Sie bei jeder Iteration eine Teilmenge zwischen dem aktuellen Index i und i + n, wobei n die Anzahl der im Universum verfügbaren Mengen ist. Was wir beim Schleifen suchen, ist eine sich wiederholende Sequenz der Größe n, die der Anzahl der Mengen im Universum entspricht.

Wenn diese Untermenge bei i gleich der Untermenge bei n ist, bedeutet dies, dass das Element bei i n-mal wiederholt wird, was gleich der Gesamtanzahl von Mengen ist. Und da es in keiner Menge Wiederholungen gibt, bedeutet dies, dass jede der Mengen diesen Wert enthält, und wir fügen ihn der Schnittmenge hinzu. Dann verschieben wir den Index um i +, was zwischen ihm und n verbleibt, da definitiv keiner dieser Indizes eine sich wiederholende Sequenz bilden wird.

3
Ayman Farhat

Sortieren Sie zunächst beide Listen mithilfe von Quicksort: O (n * log (n). Vergleichen Sie dann die Listen, indem Sie zuerst die niedrigsten Werte durchsuchen und die allgemeinen Werte hinzufügen. Beispiel: in lua):

function findIntersection(l1, l2)
    i, j = 1,1
    intersect = {}

    while i < #l1 and j < #l2 do
        if l1[i] == l2[i] then
            i, j = i + 1, j + 1
            table.insert(intersect, l1[i])
        else if l1[i] > l2[j] then
            l1, l2 = l2, l1
            i, j = j, i
        else
            i = i + 1
        end
    end

    return intersect
end

das ist O(max(n, m)), wobei n und m die Größen der Listen sind.

BEARBEITEN: quicksort ist rekursiv, wie in den Kommentaren erwähnt, aber es sieht so aus, als gäbe es nicht rekursivImplementierungen

2
Wookai

Wenn es eine Unterstützung für Mengen (wie Sie sie im Titel nennen) als eingebaut gibt, gibt es normalerweise eine Schnittmethode.

Wie auch immer, wie jemand sagte, könnten Sie es leicht machen (ich werde keine Postleitzahl veröffentlichen, jemand hat es bereits getan), wenn Sie die Listen sortiert haben. Wenn Sie keine Rekursion verwenden können, gibt es kein Problem. Es gibt rekursionslose schnelle Sortierung Implementierungen.

1
Andrea Ambu

Ich stimme der Idee der "Sets" zu. In JavaScript können Sie die erste Liste zum Auffüllen eines Objekts verwenden und dabei die Listenelemente als Namen verwenden. Anschließend verwenden Sie die Listenelemente aus der zweiten Liste und prüfen, ob diese Eigenschaften vorhanden sind.

1
Nosredna

Warum nicht eine eigene einfache Hash-Tabelle oder ein eigenes Hash-Set implementieren? Es lohnt sich, Nlogn-Überschneidungen zu vermeiden, wenn Ihre Listen so umfangreich sind, wie Sie es sagen.

Da Sie zuvor ein wenig über Ihre Daten wissen, sollten Sie in der Lage sein, eine gute Hash-Funktion zu wählen.

1
Imran

Aus der Definition der Big-Oh-Notation:

T (N) = O(f(N)) wenn es positive Konstanten c und n 0 gibt, so dass T(N) ≤ cf (N) wenn N ≥ n 0.

Was in der Praxis bedeutet, dass, wenn die beiden Listen relativ klein sind, sagen Sie, dass weniger als 100 Elemente in jeweils zwei for-Schleifen gut funktionieren. Durchlaufen Sie die erste Liste und suchen Sie im zweiten nach ähnlichen Objekten. In meinem Fall funktioniert es einwandfrei, da meine Listen nicht mehr als 10 - 20 Elemente enthalten. Eine gute Lösung ist jedoch, das erste O (n log n) zu sortieren, das zweite auch O (n log n) zu sortieren und zusammenzuführen, ein anderes O (n log n), das ungefähr O (3 n log n) sagt Die beiden Listen sind gleich groß.

0
Adelin

Ich habe einige gute Antworten von this erhalten, damit Sie sich bewerben können. Ich habe noch keine Chance, sie auszuprobieren, aber da sie auch Kreuzungen abdecken, können Sie sie nützlich finden.

0
StingyJack