Wie finden Sie die kth kleinste element in der Vereinigung von zwei sortierten arrays?
Dies ist eine Hausaufgaben Frage. Sie sagen, es dauert O(logN + logM)
wo N
und M
sind die arrays Längen.
Let name des arrays a
und b
. Natürlich können wir das alles ignorieren a[i]
und b[i]
wo ich > k.
Zuerst vergleichen wir a[k/2]
und b[k/2]
. Lassen Sie b[k/2]
> a[k/2]
. Deshalb können wir verwerfen auch alle b[i]
, wo ich > k/2.
Nun haben wir alle a[i]
, wo ich < k und alle b[i]
, wo ich < k/2 um die Antwort zu finden.
Was ist der nächste Schritt?
Wurden alle diese Schritte, die in der Aufgabe enthalten ist, oder sind die oben genannten Schritte den Beginn Ihres Algorithmus?
Die oben genannten Schritte sind von mir.
Ist
Keine Vorverarbeitung erwartet.
Duplikate sind erlaubt in den arrays?
Die oben genannten Schritte sind von mir.
Ist
O(logN + logM)
nur mit Bezug auf die Zeit, die es dauert, zu finden, die kth-element? Kann eine Vorverarbeitung durchgeführt werden, um die union vorher?Keine Vorverarbeitung erwartet.
Duplikate sind erlaubt in den arrays?
InformationsquelleAutor Michael | 2011-01-05
Du musst angemeldet sein, um einen Kommentar abzugeben.
Haben Sie es, gehen Sie einfach weiter! Und seien Sie vorsichtig mit den Indizes...
Zu vereinfachen ein bit-ich nehme an, dass N und M sind > k, so dass die Komplexität hier O(log k), O(log N + log M).
Pseudo-code:
Zur demonstration können Sie die loop-invariante i + j = k, aber ich werde nicht alles tun, Ihre Hausaufgaben 🙂
Wie kommt es, O(log k) ist in O(log n + log m) ?
Das funktioniert nicht, wenn alle Werte im array 1 kommen, bevor die Werte in array 2.
Eigentlich ist dies schlichtweg falsch. Es funktioniert überhaupt nicht.
Warum hast du k/4, die als ein Schritt auf den ersten?
InformationsquelleAutor Jules Olléon
Ich hoffe ich bin nicht zu beantworten, Sie Ihre Hausaufgaben, wie es seit über einem Jahr, seit diese Frage gestellt wurde. Hier ist eine tail-rekursive Lösung, die dauern wird log(len(a)+len(b)) Zeit.
Annahme: Die Eingänge sind Recht. also ist k im Bereich [0, len(a)+len(b)]
Basis Fälle:
Reduzierung Schritte:
a
+ mid indexb
ist weniger alsk
a
größer ist als Mitte elementb
können wir ignorieren die erste Hälfte desb
passenk
.a
passenk
.k
ist weniger als die Summe der mittleren Indizes dera
undb
:a
größer ist als Mitte elementb
können wir getrost ignorieren zweiten Hälfte desa
b
Code:
Bitte beachten Sie, dass meine Lösung ist die Schaffung neuer Exemplare kleinere arrays, die in jeder Anruf, dies kann einfach behoben werden, indem nur vorbei an start-und end-Indizes der ursprünglichen arrays.
kthlargest()
es gibt(k+1)
-th kleinsten Elemente z.B.1
ist die zweite kleinste element in0,1,2,3
d.h., Ihre Funktion zurücksorted(a+b)[k]
.ich konvertiert haben, Ihren code zu C++. Es scheint zu funktionieren
könnten Sie bitte erklären, warum ist es wichtig zu vergleichen, die Summe der mittleren Indizes von a und b mit k?
In der Reduzierung der Schritte, ist es wichtig, um loszuwerden, eine Reihe von Elementen, die in einem der arrays proportional zu seiner Länge, um die Laufzeit logarithmisch. (Hier sind wir loszuwerden, die Hälfte). Um dies zu tun, wählen Sie ein array, dessen eine der Hälften wir ignorieren können. Wie machen wir das? Durch getrost eliminieren, die Hälfte wir sicher wissen, dass Sie nicht gehen, um die kth element.
es funktioniert für mich. Ich bekomme 10 als die Antwort, die erwartet wird mit 0-basierte Indizierung.
InformationsquelleAutor lambdapilgrim
Viele Menschen beantworten diese "kth kleinste element aus den beiden sortierten array" - Frage, aber in der Regel mit nur Allgemeine Ideen, nicht eine klare funktionierenden code oder Randbedingungen Analyse.
Hier möchte ich zu erarbeiten, ihn vorsichtig mit der Art, wie ich ging, obwohl zu helfen, einige Novizen zu verstehen, mit meinem funktionierenden Java-code.
A1
undA2
sind zwei aufsteigend sortiert arrays, mitsize1
undsize2
als Länge jeweils. Wir müssen feststellen, dass die k-te kleinste element aus der Vereinigung der beiden arrays. Hier wir davon ausgehen, dass(k > 0 && k <= size1 + size2)
, was bedeutet, dassA1
undA2
können nicht beide leer.Zunächst nähern wir uns dieser Frage mit einem langsamen O(k) Algorithmus. Die Methode ist zu vergleichen das erste element der array
A1[0]
undA2[0]
. Nehmen Sie das kleinere, sagenA1[0]
Weg in unsere Tasche. Dann vergleichen SieA1[1]
mitA2[0]
, und so weiter. Wiederholen Sie diese Aktion, bis unsere Tasche erreichtk
Elemente. Sehr wichtig: Im ersten Schritt können wir nur BegehenA1[0]
in der Tasche. Wir können NICHT ein-oder ausschließenA2[0]
!!!Den folgenden O(k) - code gibt Ihnen ein element, bevor die richtige Antwort. Hier verwende ich es, um zu zeigen, meine Idee und Analyse zu den Randbedingungen. Ich habe richtige code wird nach diesem:
Die mächtigste Idee ist, dass in jeder Schleife, verwenden wir immer die base-case-Ansatz. Nach engagiert sich für die aktuelle kleinste element, bekommen wir einen Schritt näher an das Ziel: die k-te kleinste element. Springen Sie nie in der Mitte an und machen Sie sich verwirrt und verloren!
Durch die Beobachtung der oben genannten code-base-case -
k == 1, k == size1+size2
, und kombinieren Sie mit, dassA1
undA2
können nicht beide leer sein. Wir können die Logik in unter präziser Stil.Hier ist eine langsame, aber korrekte Arbeitsweise-code:
Nun können wir versuchen einen schnelleren Algorithmus läuft in O(log k). Ebenso vergleichen
A1[k/2]
mitA2[k/2]
; wennA1[k/2]
kleiner ist, dann werden alle Elemente ausA1[0]
zuA1[k/2]
sollte in der Tasche. Die Idee ist, nicht nur verpflichten, ein element in jeder Schleife; der erste Schritt enthältk/2
Elemente. Wieder, wir können NICHT ein-oder ausschließenA2[0]
zuA2[k/2]
sowieso. Also im ersten Schritt, können wir nicht mehr gehen, alsk/2
Elemente. Für den zweiten Schritt, können wir nicht mehr gehen, alsk/4
Elemente...Nach jedem Schritt, den wir viel näher an das k-te element. In der gleichen Zeit jeden Schritt immer kleiner und kleiner, bis wir
(step == 1)
, die(k-1 == index1+index2)
. Dann beziehen wir uns auf die einfache und mächtige base case wieder.Hier ist der funktionierende korrekte code:
Einige Leute können Sorge, was ist, wenn
(index1+index2)
Sprung über die k-1? Könnte, verpassen wir die base-case -(k-1 == index1+index2)
? Das ist unmöglich. Sie können bis 0.5+0.25+0.125... und Sie werden nie darüber hinaus gehen 1.Natürlich, es ist sehr einfach, schalten Sie den obigen code in rekursiver Algorithmus:
Hoffe, dass die oben genannten Analyse-und Java-code könnte helfen, Sie zu verstehen. Aber kopieren Sie niemals mein code, wie Sie Ihre Hausaufgaben! Cheers 😉
Im ersten code, sollte nicht
else if (A1[size1 - 1].compareTo(A2[size2 - 1]) < 0)
stattelse if (A1[size1 - 1].compareTo(A2[size2 - 1]) > 0)
? (In kthSmallestSlowWithFault code)Danke @Fei. Tolle Erklärung. Es ist erstaunlich, wie viele falsche Antworten kursieren über das internet in Bezug auf dieses problem. Es ist noch erstaunlicher, dass die akzeptierte Antwort, die Sie auf SO in Bezug auf diese Frage ist immer die falsche. Scheint, wie niemand kümmert sich um testen Sie die Antworten.
Vielleicht cutoff von O(k) Lösung nach einigen Schritten (so 15), Schritte Bereich sinken ziemlich schnell.
In keiner der rekursiven Aufrufe den Größen A1 oder A2 reduziert werden.
InformationsquelleAutor Fei
Hier ist ein C++ - iterative version von @lambdapilgrim Lösung (siehe die Erläuterung des Algorithmus):
Es funktioniert für alle
0 <= n < (size(a) + size(b))
Indizes und hatO(log(size(a)) + log(size(b)))
Komplexität.Beispiel
InformationsquelleAutor jfs
Mein Versuch für die ersten k zahlen, kth-Nummer in 2 sortierte arrays und n sortiert arrays:
Den kompletten code mit debug utils finden Sie unter: https://github.com/brainclone/teasers/tree/master/kth
InformationsquelleAutor Qichao Dong
Hier ist mein code basiert auf Jules Olleon Lösung:
InformationsquelleAutor superb
Hier ist meine Implementierung in C, können Sie sich an @Jules Olléon 's erklärt für den Algorithmus: die Idee hinter dem Algorithmus ist, dass wir erhalten i + j = k, und finden sich solche i und j, so dass a[i-1] < b[j-1] < a[i] (oder Umgekehrt). Jetzt da ich die Elemente 'a' kleiner als b[j-1], j-1 Elemente in 'b' kleiner als b[j-1], b[j-1] ist die i + j-1 + 1 = te kleinste element. Sie zu finden, wie i,j der Algorithmus hat eine dichotomic Suche auf den arrays.
InformationsquelleAutor Zhiwen Fang
Hier ist meine Lösung. Der C++ code druckt die kth kleinsten Wert sowie die Anzahl von Iterationen, um die kth kleinste Wert mit Hilfe einer Schleife, die meiner Meinung nach in der Größenordnung von log(k). Der code jedoch Voraus, dass k kleiner als die Länge des ersten array-das ist eine Einschränkung.
InformationsquelleAutor Karthikeyan Sv
Den ersten pseudo-code oben, funktioniert nicht für viele Werte. Zum Beispiel,
hier sind zwei arrays.
int[] a = { 1, 5, 6, 8, 9, 11, 15, 17, 19 };
int[] b = { 4, 7, 8, 13, 15, 18, 20, 24, 26 };
Es hat nicht funktioniert, für k=3 und k=9. Ich habe eine andere Lösung. Es ist unten gegeben.
Aber... es ist auch nicht die Arbeit für k=5. Es ist das gerade/ungerade-Fang von k, die nicht lassen Sie es einfach sein.
InformationsquelleAutor sn.anurag
InformationsquelleAutor Hrishikesh Mishra
Hier ist meine Lösung in java . Werde versuchen weiter zu optimieren, ist es
Diese ist inspiriert von Algo bei wunderbare youtube-video
InformationsquelleAutor M Sach
Link zu code Komplexität (log(n)+log(m))
Link zu Code (log(n)*log(m))
Umsetzung (log(n)+log(m)) Lösung
Hinzufügen möchte ich, dass meine Erklärung für das problem.
Dies ist ein klassisches problem, wo wir mit der Tatsache, dass die beiden arrays sortiert sind .
wir haben gegeben zwei sortierte arrays arr1 der Größe sz1 und arr2 Größe sz2
a)Können angenommen, wenn
Prüfen, Ob k gilt
dann können wir nicht finden kth kleinste element in der Vereinigung der beiden sortierten arrays ryt Also Ungültige Daten.
b)Nun, wenn oben genannte Bedingung hält, falsch und wir haben wirksame und durchführbare Wert von k,
Verwalten Von Edge-Fällen
Wir werden Anhängen, sowohl die arrays von -infinity-Werte an Vorder-und +unendlich-Werte am Ende zur Abdeckung der Grenzfälle k = 1,2 und k = (sz1+sz2-1),(sz1+sz2)etc.
Haupt-Algorithmus
Nun,wir tun binäre Suche auf arr1 .Wir tun binäre Suche auf arr1 suchen einen index i , startIndex <= i <= endIndex
so, dass, wenn wir finden Sie die entsprechenden index j in arr2 mit Hilfe von constraint {(i+j) = k},dann, wenn
Da wir wissen, dass die kth kleinste element der (k-1) Elemente, die kleiner als es in der Vereinigung der beiden arrays ryt? So,
In Case1, was wir getan haben , haben wir sichergestellt, dass es eine Summe von (k-1) kleinere Elemente zu arr1[i], weil die Elemente, die kleiner als arr1[i] in array arr1 i-1 an der Zahl, als wir wissen (arr2[j-1] < arr1[i] < arr2[j]) und Anzahl der Elemente, die kleiner als arr1[i] arr2 ist j-1 wegen j gefunden mit (i-1)+(j-1) = (k-1), So kth kleinste element wird arr1[i]
Aber die Antwort kann nicht immer aus der ersten array-ie arr1 so checkten wir für case2 die auch erfüllt ähnlich wie Fall 1, da (i-1)+(j-1) = (k-1) . Nun, wenn haben wir (arr1[i-1] < arr2[j] < arr1[i]) haben wir insgesamt k-1 Elemente kleiner als arr2[j] in die Vereinigung der beiden arrays so sein das kth kleinste element.
In case3 , bilden Sie zu jedem der Fall 1 oder Fall 2, wir müssen Inkrement i und j wird gefunden, nach mit Hilfe von constraint {(i+j) = k} ie in binärer Suche, nach rechts verschieben Teil ie machen startIndex = middleIndex
In case4, bilden Sie zu jedem der Fall 1 oder Fall 2, wir brauchen, um zu Dekrementieren i und j wird gefunden, nach mit Hilfe von constraint {(i+j) = k} ie in binäre Suche nach Links verschieben Teil ie machen endIndex = middleIndex.
Nun, wie zu entscheiden, startIndex und endIndex am Anfang der binären Suche über arr1
mit startindex = 1 und endIndex = ??.Wir müssen uns entscheiden.
Weil wenn k größer ist als die Größe des ersten Arrays, die wir haben können, binäre Suche über das gesamte array arr1 sonst brauchen wir nur die ersten k Elemente, weil sz1-k-Elemente können niemals einen Beitrag in die Berechnung der kleinsten kth.
CODE Unten Gezeigte
Für die Lösung der Komplexität (log(n)*log(m))
Nur ich verpasste mit Vorteil von der Tatsache, dass für jedes i das j gefunden werden können, mit Hilfe von constraint {(i-1)+(j-1)=(k-1)}, So dass für jedes i ich wurde weiter anwenden binäre Suche auf dem zweiten array zu finden j, so dass arr2[j] <= arr1[i].Also diese Lösung kann noch weiter optimiert werden
InformationsquelleAutor Vinayak Sangar
Grundsätzlich über diesen Ansatz können Sie verwerfen k/2 Elemente bei jedem Schritt.
Der K wird rekursiv ändern von k => k/2 => k/4 => ... bis Sie 1 erreicht.
So, die Zeit-Komplexität ist O(logk)
Bei k=1 ist , erhalten wir die niedrigste der beiden arrays.
Den folgenden code in JAVA. Bitte beachten Sie, dass wir die Subtraktion von 1 (-1) den code aus der Indizes, da ein Java-array-index beginnt mit 0 und nicht mit 1, zB. k=3 dargestellt ist, indem das element in der 2. index in einem array.
InformationsquelleAutor FaaduBaalak
Zeit Complexcity ist O(log(min(n,m)))
InformationsquelleAutor HeadAndTail
Überprüfen Sie diesen code.
InformationsquelleAutor Anantha Krishnan
Unterhalb von C# - code zu Finden, der die k-te Kleinste Element in der Union von Zwei Sortierte Arrays. Time Komplexität : O(logk)
es ist kein bug, ich habe getestet, mein code, bevor ich gebucht, um SO
Dank sammy333, ich habe aktualisiert, der code. jetzt seine Arbeit ein
(Berechnen Sie
midA
ausendA
wennk < n
. Überprüfen Sie für kurze arrays, beginnend mitreturn B[startB + k - 1];
.)InformationsquelleAutor Piyush Patel