Methoden Vergleichen von zwei Listen in der Geschwindigkeit von O(n+m)

SnrufjStill

Mitglied
Hallo, bin die ganze Zeit am Rumdenken komme aber auf nichts Vernünftiges.

Aufgabe:
Zwei Listen Folgen den Regeln der Mengenlehre (es dürfen keine doppelten Elemente in einer Liste sein) ich soll nun die Methode Vereinigung (
fee055b62470bc8713ed312fb67bbc55.png
) schreien, die steht auch und funktioniert. Jetzt soll sie optimiert werden und in O(m+n) durchlaufen, dabei steht n für die Hauptliste und m für die neue Liste, die dazukommt.

Also durchläuft die Methode einmal Liste 1 und einmal Liste 2 (?)

Momentane Situation:
Ich durchlaufe in der Methode die zweite Liste mit einem Iterator und Vergleiche jedes Element mit der in der ersten Liste mithilfe der Methodecontains, die auch nur eine Art Iterator ist. Also bin ich bei... m + n^n (n hoch n) ?

Egal wie ich es drehe und wende ich komme nicht darauf, wie ich es optimieren kann. Es wird ja am ende immer ein Vergleich benötigt, wenn ein neues Element dazu kommt(da es keine doppelten werte haben darf [ich teste es gerade mit Integer]).
 

Kababär

Top Contributor
Sind die Listen sortiert?
Dann könntest du ggf einen einfachen Algorithmus schreiben für einen iterator, sodass du bei O(n+m) landest.

Falls die Liste nicht sortiert ist, sortiere sie. Dann musst du nicht immer von vorne anfangen.

Mit einem virtuellen Zeiger A und B hälst du jeweils eine Referenz auf die Listen X und Y. Fange bei dem kleineren wert an und gehe solange durch, bis der ursprünglich kleinere wert nicht mehr kleiner ist. Nehme den anderen Zeiger und tue das selbe. Etc

Wo genau liegt das Problem?
Oder verstehe ich dich falsch?
 

Flown

Administrator
Mitarbeiter
Also einfügen kann nur mit O(n) für n Elemente passieren, wenn der Lookup O(1) - wie bei Sets - hat.
 

Flown

Administrator
Mitarbeiter
Anders gesagt, wenn du erst überprüfen müsstest ob ein Wert in der Liste gespeichert ist(Lookup) hat das eine Komplexität von O(n). Klar oder? Du musst durch die ganze Liste iterieren und im worst-case ist das eben das letzte Element. Wenn du dann n Elemente einfügen möchtest musst du eben n * n Überprüfungen starten => O(n²).
Darum brauchst du wie ich oben schon erwähnt habe einen Lookup O(1) und der wird mit HashCode normalerweise erreicht.
 

Flown

Administrator
Mitarbeiter
Der best-case für eine sortierte Liste, um ein Element zu finden ist O(log n). Das heißt sortiert einfügen hat eine Komplexität von O(n * log n). Daher braucht man Datenstrukturen, die das "besser" oder sagen wir effizienter lösen. Das ist de facto eine Hashimplementierung (HashSet).
Also ein Algorithmus der O(n + m) Komplexität besitzt sieht so aus:
Java:
/**
 * Merges two <code>Lists</code> which behave like <code>Sets</code> and forms
 * the union. The result is given in the first provided <code>List</code>.<br>
 * <i>Note</i>: This implementation has a time complexity of
 * <code>O(n + m)</code>.
 * 
 * @param <T>
 *          type of the <code>List</code> elements
 * @param n
 *          the first set of elements and the result container.
 * @param m
 *          the second set of elements.
 */
public static <T> void union(List<T> n, List<T> m) {
  Set<T> seen = new HashSet<>(n);
  for (T t : m) {
    if (seen.add(t)) {
      n.add(t);
    }
  }
}
 

JStein52

Top Contributor
Sorry wenn ich da drauf rumreite, aber hier sehe ich erst mal nur dass das im Kommentar steht. Und im Code dazu erkenne ich erst mal O(m) ... aber was tut seen.add(t)) ? Mir fehlt die schlüssige Erklärung des Algorithmus mit dem sich O(n+m) begründen lässt.
 

Flown

Administrator
Mitarbeiter
Das Set wird initialisiert mit den Werten von Liste n, dass funktioniert mit einer Komplexität von O(n). Dann wird über die Liste m iteriert.
Hier passiert folgendes: seen.add(t). Genauer: Ist das Element in dem Set enthalten? Wenn ja dann gibt die Methode false zurück. Wenn nein, dann fügt es das Element dem Set hinzu und gibt true zurück. Was genau passiert bei dem add? Also in der JavaDoku selbst ist beschrieben:
This class offers constant time performance for the basic operations (add, remove, contains and size), assuming the hash function disperses the elements properly among the buckets....
Vom Element wird der hashCode berechnet und auf die Länge des Backing-Array getrimmt. Dann wird geprüft ob in diesem "Bucket" ein Element exisitiert oder nicht. Passiert alles in konstanter Zeit.
Hinzufügen eines Elements in eine Liste (meist) konstant und das jetzt für m Elemente also: O(m).
Beides gemeinsam ist dann: O(n + 1 * m) <=> O(n + m)
 

JStein52

Top Contributor
Mhmmm, also ich kann mir nicht vorstellen dass diese Erklärung in einer Klausur zu dem Thema durchgehen würde: "das ist so weil im Kommentar zu HashSet steht es ist O(1) ... "

Es muss doch einen Algorithmus geben mit dem man dies erklären kann, unabhängig von Java und irgendwelchen dortigen Kommentaren ?
Genauer: Ist das Element in dem Set enthalten?
Dieser lapifare Satz ist doch der unklare Punkt ! Wie geht das mit O(1)
 

JStein52

Top Contributor
Es würde gehen wenn man direkt mit dem Hashcode eines Elementes das Element selber addressieren kann und deshalb nur einen einzigen Zugriff braucht. Aber wie ?
 

mrBrown

Super-Moderator
Mitarbeiter
Es würde gehen wenn man direkt mit dem Hashcode eines Elementes das Element selber addressieren kann und deshalb nur einen einzigen Zugriff braucht. Aber wie ?

Passiert doch bei HashSet/HashMap?
Der HashCode wird berechnet, auf die Länge des dahinterliegenden Arrays getrimmt. Passiert in O(1). das dahinterliegende Bucket muss noch durchgegangen werden, ist aber vernachlässigbar (und im Idealfall bei guter Hashfunktion und großen Tabellen auch O(1)).
 

InfectedBytes

Top Contributor
Das ist eben eine der grundlegenden Eigenschaften von Hashtabellen. Wobei eben dazu gesagt werden muss, dass es sich bei dem O(1) nur um den average case handelt. Der worst case ist O(n).
Mit einer perfekten Hash Funktion könnte man sogar den worst case auf O(1) bringen, was jedoch praktisch nicht so einfach möglich ist.

Es würde gehen wenn man direkt mit dem Hashcode eines Elementes das Element selber addressieren kann und deshalb nur einen einzigen Zugriff braucht. Aber wie ?
Das machen Hashsets ja (mehr oder weniger). Der Grundgedanke ist, das die Hashfunktion aus einem gegeben Objekt den hash berechnet und dieser dann direkt als Index betrachtet werden kann. Im Detail ist das natürlich etwas aufwendiger, da man ja nicht unendlich viel speicher reservieren kann und es je nach Hashfunktion kollisionen geben kann etc.

edit: zu langsam^^
 

JStein52

Top Contributor
Das machen Hashsets ja (mehr oder weniger). Der Grundgedanke ist, das die Hashfunktion aus einem gegeben Objekt den hash berechnet und dieser dann direkt als Index betrachtet werden kann.
Das ist mir ja alles klar. Meine Frage war ja auch nur wie ? Und wie du ja selbst sagst:
Der worst case ist O(n).

Ich habe ja nur so ein bisschen das Gefühl dass wir hier keinen Algorithmus diskutieren wie der TO das mit O(n+m) schaffen kann sondern dass wir die Komplexität auf HashSet outsourcen und sagen das wird schon so sein. Ich habe mir natürlich auch die JavaDoc zu HashSet angeschaut aber da wird ja auch genau mit den Begriffen hantiert die ihr oben benutzt habt. Für mich wäre das als Antwort in einer Klausur nicht ausreichend aber vielleicht ist der TO ja schon lange zufrieden ;););)
 

JStein52

Top Contributor
Ja genau. kommt halt auf den ganzen Kontext der Aufgabe an. Der TO hat ja jetzt seine Vereinigungsmethode in Java geschrieben, aber vielleicht geht es ja ganz allgemein um rein akademische Fragen unabhängig von einer Programmiersprache und Java wird nur zur Demonstration des gewählten Algorithmus benutzt ?
@SnrufjStill : vielleicht kannst du uns mehr dazu sagen. Und mich würde hier auch die "gewünschte" Lösung interessieren falls du die mal kriegst.
 

Flown

Administrator
Mitarbeiter
@JStein52 Was verstehst du an dem Hashing/Caching Algorithmus nicht?
Habs doch noch extra hinzugeschrieben:
Vom Element wird der hashCode berechnet und auf die Länge des Backing-Array getrimmt. Dann wird geprüft ob in diesem "Bucket" ein Element exisitiert oder nicht. Passiert alles in konstanter Zeit.
Um das für int Zahlen zu konkretisieren setze doch für hashCode = Eigenwert und für Bucket ein int[] array ein.
 

Flown

Administrator
Mitarbeiter
So war mal auf Mittag... Hier ist eine Implementierung für byte[] mit perfekter Hashfunktion:
Java:
public static byte[] union(byte[] n, byte[] m) {
  int newLength = n.length;
  byte[] result = Arrays.copyOf(n, n.length + m.length);

  boolean[] seen = new boolean[1 << Byte.SIZE];

  for (byte b : n) {
    add(seen, b);
  } // <=> new HashSet<>(n);

  for (byte b : m) {
    if (add(seen, b)) { // <=> seen.add(t);
      result[newLength++] = b;
    }
  }
  return Arrays.copyOf(result, newLength);
}

public static boolean add(boolean[] set, byte element) {
  int idx = hash(element);
  if (!set[idx]) {
    return set[idx] = true;
  }
  return false;
}

private static int hash(byte b) {
  return Byte.toUnsignedInt(b);
}
So funktioniert auch ein HashSet und das ist jetzt wirklich heruntergebrochen auf das Minimum. Alles andere wäre jetzt für mich zu viel Aufwand gewesen.
 

JStein52

Top Contributor
So ähnlich hatte ich mir das vorhin auch schon mal überlegt. Aber ich habe dann nicht mehr weiter gemacht weil ich nicht mehr so sicher war wie ich das:

Code:
boolean[] seen = new boolean[1 << Byte.SIZE];
im allgemeinen Fall dimensioniere. Für byte ist ja noch relativ einfach und einsichtig. Und klar dass das auch mit der verwendeten Hash-Funktion zusammenpassen muss. Und an der Stelle habe ich dann aufgehört. ;););)
 

mrBrown

Super-Moderator
Mitarbeiter
im allgemeinen Fall dimensioniere. Für byte ist ja noch relativ einfach und einsichtig. Und klar dass das auch mit der verwendeten Hash-Funktion zusammenpassen muss. Und an der Stelle habe ich dann aufgehört. ;););)

Der Weg nur mit Arrays funktioniert nur, wenn die HashFunktion keine Kollisionen ergeben kann, und wenn das der Fall ist, sollte auch die Anzahl der Möglichkeiten bekannt sein. Im Zweifel sind's dann halt 1l << Integer.SIZE
 

Tobse

Top Contributor
Mir gehts ein bisschen so wie @JStein52: Einen eigenständigen Algorithmuss würde ich auch gerne sehen.

Der Weg nur mit Arrays funktioniert nur, wenn die HashFunktion keine Kollisionen ergeben kann, und wenn das der Fall ist, sollte auch die Anzahl der Möglichkeiten bekannt sein. Im Zweifel sind's dann halt 1l << Integer.SIZE
In der Theorie erreicht man damit konstante Zeit. In der Praxis kann man aber nicht 2GB Arbeitsspeicher für jede HashMap reservieren - womit der Worst-Case für contains() wieder O(n) ist.
Deshalb bin ich der Meinung, dass - wie bereits gesagt wurde - die Frage gar nicht den Worst-Case meinen kann. Aber bis zu einer Aufklärung vom TE ist das eh pure Spekulation.
 

klauskarambulut

Bekanntes Mitglied
Bei einem Merge Sort hat man gegen Ende auch zwei sortierte Listen die zu einer sortierten Liste vereinigt werden.
Dieser Schritt hat dann O(m+n).
Wenn die Hashfunktion bijektiv ist, dann sind die Liste, das Set auch in O(1) sortierbar, womit man dann beim Mergesort ist.
 

Meniskusschaden

Top Contributor
Wenn die Hashfunktion bijektiv ist, dann sind die Liste, das Set auch in O(1) sortierbar, womit man dann beim Mergesort ist.
Davon habe ich noch nie etwas gehört und kann mir das gerade auch überhaupt nicht vorstellen. Hast du nähere Infos dazu, wie man das macht? Ehrlich gesagt bezweifle ich, dass es funktioniert.
Aber nur deshalb, weil es Dubletten geben darf; ergo müssen sie nicht herausgefiltert werden. Da ist O(m+n) einfach
Der Merge-Schritt funktioniert auch mit Dubletten einfach in O(m+n).
 

Flown

Administrator
Mitarbeiter
Ich weiß echt nicht was hier noch das Problem ist. Algorithmen werden meist im average case angegeben. Wie sollte man sonst einen Algorithmus schreiben können mit O(n + m) für Setoperationen. Wenn jemand diesen im worst case liefern kann dann immer her damit.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
I Alle Elemente von zwei Listen vergleichen Java Basics - Anfänger-Themen 1
I Zwei Listen vergleichen Java Basics - Anfänger-Themen 2
I Zwei Listen vergleichen bei n:m Beziehung Java Basics - Anfänger-Themen 2
I Zwei Listen vergleichen Java Basics - Anfänger-Themen 7
S Aktuell beste Methode um zwei Bilder zu vergleichen..? Java Basics - Anfänger-Themen 1
Bademeister007 Elemente aus zwei verschiedenen Arrays miteinander vergleichen und gegeben falls entfernen Java Basics - Anfänger-Themen 14
J Zwei Objekte vergleichen Java Basics - Anfänger-Themen 8
J zwei String Arrays miteinander vergleichen Java Basics - Anfänger-Themen 18
N Zwei Daten (Datum) miteinander vergleichen, abspeichern, laden Java Basics - Anfänger-Themen 4
L Erste Schritte Elemente zwei Schlangen vergleichen Java Basics - Anfänger-Themen 14
N Zwei Strings mit "==" vergleichen warum TRUE Java Basics - Anfänger-Themen 2
H Bubblesort-Zwei Integer auf Dekade vergleichen. Java Basics - Anfänger-Themen 6
L Rekursiv zwei Strings vergleichen Java Basics - Anfänger-Themen 3
J Zwei String-Variabeln vergleichen Java Basics - Anfänger-Themen 5
D Zwei ArrayListen<String> vergleichen. Java Basics - Anfänger-Themen 11
C Werte aus zwei Objekten miteinander vergleichen Java Basics - Anfänger-Themen 3
M Zwei Strings vergleichen? Java Basics - Anfänger-Themen 10
Joew0815 Zwei ArrayListen mit einander vergleichen Java Basics - Anfänger-Themen 33
S zwei Datumswerte vergleichen Java Basics - Anfänger-Themen 3
J Zwei Dateien miteinander vergleichen Java Basics - Anfänger-Themen 11
K Zwei Daten Vergleichen Java Basics - Anfänger-Themen 6
P Zwei Wörter vergleichen Java Basics - Anfänger-Themen 11
Q Zwei Strings vergleichen Java Basics - Anfänger-Themen 14
M Zwei Objekt Inhalte vergleichen Java Basics - Anfänger-Themen 22
M zwei array inhalte vergleichen Java Basics - Anfänger-Themen 3
M zwei int vergleichen geht nicht Java Basics - Anfänger-Themen 16
T zwei BigDecimal vergleichen Java Basics - Anfänger-Themen 2
M Vergleichen, ob eine Liste länger als andere ist Java Basics - Anfänger-Themen 6
E Arrays in einer ArrayList miteinander vergleichen Java Basics - Anfänger-Themen 12
A Daten aus einer HashMap aus einer DB speichern und mit neuen Werten vergleichen Java Basics - Anfänger-Themen 8
I 2 verschiedene Klassen mit gleichen Property vergleichen Java Basics - Anfänger-Themen 13
J 2 listen vergleichen, die auch null Elemente haben können ! Java Basics - Anfänger-Themen 9
J ArrayList vergleichen im spiel Mastermind Java Basics - Anfänger-Themen 2
J Array.list vergleichen Java Basics - Anfänger-Themen 1
M 3 Zahlen miteinander vergleichen Java Basics - Anfänger-Themen 18
S Inhalte aus Array vergleichen und Max ausgeben Java Basics - Anfänger-Themen 3
B bei 2 Arrays Anzahl gleicher Elemente vergleichen? Java Basics - Anfänger-Themen 49
W LocalDate vergleichen mit Equals? Java Basics - Anfänger-Themen 7
S mehrere TreeSets so speichern, dass man sie miteinander vergleichen kann Java Basics - Anfänger-Themen 1
ArrayList mit unbekannter Menge an Arrays die Arrays vergleichen Java Basics - Anfänger-Themen 9
M String mit Variable vergleichen Java Basics - Anfänger-Themen 9
O Array mit einem Zeichen vergleichen Java Basics - Anfänger-Themen 1
S String mit Int input vergleichen Java Basics - Anfänger-Themen 5
S Den Minimumberechnen 2 codes vergleichen Java Basics - Anfänger-Themen 4
S Chars vergleichen ohne Betrachtung der Groß und Kleinschreibung Java Basics - Anfänger-Themen 7
A 2 Strings vergleichen in einer methode wenn man mit Globalen variablen arbeitet Java Basics - Anfänger-Themen 12
districon Vergleichen von Objekten Java Basics - Anfänger-Themen 20
M Strings vergleichen Java Basics - Anfänger-Themen 10
J Zufallszahlen generieren und Werte vergleichen Java Basics - Anfänger-Themen 3
Stephan_kl Reihenwert-Berechnung, Ergebnis mit vorherigem Ergebnis vergleichen Java Basics - Anfänger-Themen 11
R Werte und Reihenfolge in 2d Arrays vergleichen Java Basics - Anfänger-Themen 5
JaVaN0oB Wörterraten - Falsche Ausgabe, String/Chars vergleichen Java Basics - Anfänger-Themen 2
O String mit Character vergleichen Java Basics - Anfänger-Themen 3
S 2 Strings mit Equals vergleichen Java Basics - Anfänger-Themen 11
N 2D Arrays jedes xy vergleichen Java Basics - Anfänger-Themen 7
M Objekte mittels equals vergleichen Java Basics - Anfänger-Themen 14
F Eine Zahl mit Arrays vergleichen Java Basics - Anfänger-Themen 7
D Vergleichen von Strings Java Basics - Anfänger-Themen 6
M Objekte miteinander vergleichen Java Basics - Anfänger-Themen 18
M Matrix Elemente vergleichen Java Basics - Anfänger-Themen 11
R String vergleichen Java Basics - Anfänger-Themen 59
S Vergleichen ob der Integer der benutzt eingeben werden soll überhaupt ein int ist Java Basics - Anfänger-Themen 1
C System.in.read() Boolsche Werte vergleichen Java Basics - Anfänger-Themen 8
K Boolean in einer Methode um 2 Objekte zu vergleichen Java Basics - Anfänger-Themen 12
A Daten auslesen/vergleichen Java Basics - Anfänger-Themen 3
J Strings untereinander in einer Liste vergleichen Java Basics - Anfänger-Themen 18
E Zahlen von einem Array mit zahlen von zweitem Array vergleichen Java Basics - Anfänger-Themen 27
A Suffix vergleichen Java Basics - Anfänger-Themen 2
PaperHat Objekte in Array vergleichen Java Basics - Anfänger-Themen 9
F Input/Output 2 Textdateien mit einander vergleichen Java Basics - Anfänger-Themen 11
M String vergleichen Java Basics - Anfänger-Themen 5
T Datentypen Kann Java 2 verschiedene Datentypen vergleichen? Java Basics - Anfänger-Themen 2
S Array, Geburtsdatum, Vergleichen Java Basics - Anfänger-Themen 28
F JList Elemente mit Strings vergleichen Java Basics - Anfänger-Themen 12
L Variablen Versionsnummern vergleichen Java Basics - Anfänger-Themen 5
N Methoden int[]'s vergleichen Java Basics - Anfänger-Themen 4
N Methoden HashMap interne Werte miteinander vergleichen Java Basics - Anfänger-Themen 7
T JPasswordFielder vergleichen Java Basics - Anfänger-Themen 16
K Datentypen Einträge zweier Matrizen vergleichen Java Basics - Anfänger-Themen 4
M Objekt mit Hashmap vergleichen Java Basics - Anfänger-Themen 22
S Werte in Liste mit Nachfolger vergleichen Java Basics - Anfänger-Themen 5
M Erste Schritte Mehrere eingaben in einer Line vergleichen (if equals...) Java Basics - Anfänger-Themen 6
J Zahlensequenz mit einer anderen Sequenz vergleichen Java Basics - Anfänger-Themen 6
P String größer kleiner gleich vergleichen Java Basics - Anfänger-Themen 6
J Methoden BinaryStrings vergleichen Java Basics - Anfänger-Themen 12
C arrey mit string vergleichen Java Basics - Anfänger-Themen 2
K Methoden Passwort Bestätigungsfeld mit Password vergleichen Java Basics - Anfänger-Themen 7
M Wortteile im String vergleichen Java Basics - Anfänger-Themen 2
J Algorithmus - Strings auf eigene Reihenfolge miteinander vergleichen Java Basics - Anfänger-Themen 4
C Große Zahlen vergleichen Java Basics - Anfänger-Themen 19
? Methoden Boolean Wert vergleichen und einlesen Java Basics - Anfänger-Themen 1
Korvinus Vergleichen von 2 csv-Dateien Java Basics - Anfänger-Themen 2
K Comparable - Objekte aus Array vergleichen und größtes auswählen Java Basics - Anfänger-Themen 1
G Passwort und Passwort wiederholen in if-Abfrage vergleichen Java Basics - Anfänger-Themen 15
JavaNewbie2.0 String vergleichen Java Basics - Anfänger-Themen 4
M 2 Stellen in einem Array vergleichen und bei übereinstimmen eine davon ersetzen Java Basics - Anfänger-Themen 1
A Methoden Char-Arrays auf aufeinanderfolgende Elemente vergleichen! Java Basics - Anfänger-Themen 7
R Objekte Vergleichen und Sortieren Java Basics - Anfänger-Themen 3
A Werte innerhalb von resultset vergleichen Java Basics - Anfänger-Themen 2
I Meta Tags vergleichen mit Html Vorgabe Java Basics - Anfänger-Themen 8

Ähnliche Java Themen

Neue Themen


Oben