@BlackJack
Die Listen brauchen nicht sortiert zu sein, sollten sie auch gar nicht, weil man sie danach ja dann wieder "teuer" in die orgininale Reihenfolge bringen müsste.
Deshalb bezog sich meine Annmerkung auch alleine auf Schnittmengen. Und da bei Mengen die Reihenfolge irrelevant ist, kann man die Listen getrost sortieren bevor man die Schnittmenge bildet.
Nebenbei: ``in`` auf Listen hat lineare Laufzeit, aber `list` ist nicht als verkettete Liste implementiert.
und linear ist die Komplexitätsklasse O(n). Durch die Indizierung (und falls die Liste sortiert sein sollte) schafft man die member-Operation sogar mit logarithmischen Aufwand. (Binäre Suche).
Ich versuche jetzt nochmal zu verdeutlichen wie ich O(n^2) komme:
a = [5,8,2,7,9], |a| = 5
b = [9,2,6,4], |b| = 4
Wenn ich jetzt das Beispiel von dir neheme heisst das:
Für alle x aus a, wenn x nicht aus b, dann mach irgendetwas. D.h. das für jedes x das man aus a nimmt, muss jedes Element aus b betrachtet werden, um entscheiden zu können ob x wirklich nicht in b ist.
Im Endeffekt werden |b| viele Elemente |a| mal betrachtet. Daraus folgt ein Aufwand von O(|a| * |b|). Sollte jetzt der Bertag von a ungefähr gleich dem Betrag von b sein, haben wir O(n^2), also quadratische Laufzeit.
Nimmt man es jetzt in Kauf die Listen erst zu sortieren (bei einem guten Sortierverfahen wie Merge Sort oder Heap Sort bei einer Komplexität von O(n * log n) ) lässt sich die Schnittmenge mit linearen (O(n)) Aufwand bilden, denn dann können beide Listen parallel durchlaufen werden.
Und O(n * log n) + O(n) ist immer noch effizienter als O(n^2) und das für alle c aus N für n0 = 1.