Möchten Sie einige Elemente aus einer Liste löschen, die in einer anderen Liste existieren wird

Karan:

Ich habe eine Liste annehmen

listA=[679,890,907,780,5230,781]

und wollen einige Elemente löschen, die in einem anderen existierte wird

listB=[907,5230]

in kürzester Zeit Komplexität?

Ich kann dieses Problem tut Mittel, durch die Verwendung von zwei „for-Schleifen“ O (n2) Zeit Komplexität, aber ich mag diese Komplexität O (nlog (n)) oder O (n) reduzieren? Ist es möglich?

avi:

Es ist möglich - wenn einer der Listen sortiert. Unter der Annahme , dass die Liste sortiert wird A und B Liste ist unsortiert, mit jeweiligen Abmessungen Mund Ndie minimale Zeitkomplexität alle Liste B der Elemente aus der Liste A zu entfernen sein wird O((N+M)*log(M)). Die Art und Weisen Sie dies erreichen können , ist durch binäre Suche - jeder Nachschlag für ein Element in der Liste A dauert O(log(M))Zeit, und es gibt NLookups (ein für jedes Element in der Liste B). Da es braucht O(M*log(M))Zeit A zu sortieren, ist es effizienter für riesige Listen alle Elemente zu sortieren und dann entfernen, mit einer Zeitkomplexität O((N+M)*log(M)).

Auf der anderen Seite, wenn Sie nicht über eine sortierte Liste haben, verwenden Sie einfach Collection.removeAll , die eine Zeitkomplexität hat O(M*N)in diesem Fall. Der Grund für diese Zeit Komplexität ist , dass removeAlltut (standardmäßig) so etwas wie der folgenden Pseudo - Code:

public boolean removeAll(Collection<?> other)
    for each elem in this list
        if other contains elem
            remove elem from this list

Da containseine Zeitkomplexität hat O(N)für Listen, und Sie am Ende tun MIterationen, nimmt diese O(M*N)Zeit insgesamt.

Schließlich, wenn Sie die Zeitkomplexität minimieren wollen removeAll(mit möglicherweise verschlechtern reale Welt Performance) können Sie folgendes tun:

List<Integer> a = ...
List<Integer> b = ...
HashSet<Integer> lookup = new HashSet<>(b);
a.removeAll(lookup);

Für schlechte Werte von b, die Zeit zu konstruieren lookupkönnte zu Zeit in Anspruch nehmen O(N*log(N)), wie gezeigt hier ( „pathologisch verteilt Keys“). Danach wird rufenden removeAllnehmen O(1)für containsüber MIterationen, wobei O(M)Zeit auszuführen. Daher ist die Zeitkomplexität dieses Ansatzes O(M + N*log(N)).

So gibt es Ansätze , drei hier. One bietet Ihnen mit der Zeit Komplexität O((N+M)*log(M)), ein anderer bietet Ihnen mit der Zeit Komplexität O(M*N)und die letzte liefert Ihnen Zeitkomplexität O(M + N*log(N)). Bedenkt man, dass die ersten und letzten Ansätze in Zeitkomplexität ähnlich sind (wie logsehr klein zu sein scheint auch für eine große Zahl), würde ich vorschlagen , mit der naiven gehen O(M*N)für kleine Eingänge und einfachsten O(M + N*log(N))für mittlere Eingänge. An der Stelle , wo die Speicherauslastung von der Erstellung einer HashSet zu leiden beginnt zu speichern , die Elemente von B (sehr große Eingänge), würde ich wechseln schließlich auf die komplexeren O((N+M)*log(M))Ansatz.

Sie können eine AbstractCollection.removeAll Implementierung finden hier .

Edit:
Der erste Ansatz für Arraylisten nicht so gut funktionieren - von der Mitte der Liste A zu entfernen braucht O(M)Zeit, offenbar. Stattdessen Sortierliste B ( O(N*log(N))), und eine Iteration durch die Liste A, Elemente gegebenenfalls zu entfernen. Dies dauert O((M+N)*log(N))Zeit und ist besser als das , O(M*N*log(M))dass Sie sich mit enden , wenn eine Arraylist verwenden. Leider erfordert die Teil dieses Algorithmus „Elemente gegebenenfalls zu entfernen“ , dass Sie Daten zu erstellen , um die nicht entfernten Elemente zu speichern O(M), wie Sie in diesem Fall keinen Zugriff auf den internen Datenfeld der Liste A. haben, ist es streng besser mit dem HashSet Ansatz zu gehen. Dies liegt daran , (1) die Zeitkomplexität O((M+N)*log(N))tatsächlich schlechter als die Zeitkomplexität für die HashSet Methode ist, und (2) der neue Algorithmus speichert nicht auf Speicher. Deshalb,Verwenden Sie nur den ersten Ansatz , wenn Sie eine Liste mit haben O(1)Zeit für die Entfernung (zB LinkedList) und eine große Menge an Daten . Andernfalls verwenden removeAll . Es ist einfacher, oft schneller, und von Bibliothek - Designer unterstützt (zB Arraylist hat eine individuelle removeAll Implementierung , die es mit vernachlässigbaren zusätzlichen Speichern anstelle der quadratischen Zeit in Anspruch nimmt linear erlaubt).

Ich denke du magst

Origin http://43.154.161.224:23101/article/api/json?id=315025&siteId=1
Empfohlen
Rangfolge