Das folgende ist eine Praxis Interview Frage, die mir von jemandem gegeben wurde, und ich bin mir nicht sicher, was die beste Lösung dazu ist:Mit einer Reihe von Bereichen S und einem überlappenden Bereich R, finden Sie die kleinste Teilmenge in S, die umfasst R
eine Reihe von Bereichen gegeben:
(zBS = {(1, 4), (30, 40), (20, 91) ,(8, 10), (6, 7), (3, 9), (9, 12), (11, 14)}
Und ein Zielbereich R gegeben (zBR = (3, 13)
- also die 3-13 gehen Bereich) einen Algorithmus schreiben.. Finde den kleinsten Satz von Bereichen, die deinen Zielbereich abdecken Alle Bereiche in dem Satz müssen sich überlappen, um als Spannweite zu gelten der gesamte Zielbereich. (In diesem Beispiel würde die Antwort{(3, 9), (9, 12), (11, 14)}
sein.
Was ist der beste Weg, dies zu lösen? Ich habe nachgedacht getan werden würde einen Greedy-Algorithmus verwendet wird. In unserem Beispiel oben, würden wir für alle aussehen von den Zahlen, die sich mit 3 schneiden, und wählen aus denen die mit dem höchsten Max. Dann würden wir dasselbe mit dem tun, was wir gerade ausgewählt haben, also, da wir (3, 9) ausgewählt haben, wollen wir nun alle finden die Bereiche, die 9 schneiden, und unter denen wählen wir den mit dem höchsten Max. In dieser Iteration haben wir (9, 12) gewählt.Wir machen dasselbe mit dem, und wir finden, dass der nächste Bereich 12 schneidet , mit dem höchsten max ist (11, 14).
Nach dieser Iteration sehen wir, dass 14 größer als 13 ist (das Maximum unserer Reichweite), damit wir aufhören können.
Das Problem, das ich mit diesem Algorithmus habe, ist, wie effizient die überschneidenden Bereiche abfragen? Wenn wir eine lineare Suche versuchen, erhalten wir einen Algorithmus, der O(n^2)
ist. Mein nächster Gedanke war, jeden unserer überschneidenden Bereiche aus unserer Liste zu streichen, wenn wir die Schleife durchlaufen. Also kreuzen wir in der ersten Iteration (1, 4) und (3, 9). In unserer nächsten Iteration kreuzen wir (9, 12), (3, 9) und (8, 10). Bei der letzten Iteration müssen wir also nur durchsehen: {(30, 40), (20, 91), (6, 7)}. Wir könnten dies noch effizienter machen, indem wir auch alles ausstreichen, was ein Minimum von> 13 und ein Maximum von < 3 hat. Das Problem ist, dass dies immer noch nicht genug ist. Es gibt immer noch das potentielle Problem, viele Doppelsequenzen im Rahmen unseres Angebots zu haben. Wenn unsere Liste von Bereichen etwas wie {(6, 7), (6, 7), (6, 7), (6, 7), (6, 7)} enthalten würde, müssten wir jedes Mal durch diese Liste schauen , obwohl sie uns nicht nützlich sind. Selbst wenn wir nur eindeutige Werte speichern sollten (indem wir sie alle in ein Set setzen), haben wir vielleicht eine sehr große Auswahl, mit einer Reihe von Bereichen, die innerhalb unseres Zielbereichs liegen, aber wir haben auch einen Bereich, der sich fast überspannt der gesamte Zielbereich.
Was wäre eine effiziente Möglichkeit, unsere Sortimente abzufragen? Oder möglicherweise, was wäre ein effizienterer Algorithmus zur Lösung dieses Problems?
Könnte eine gültige Lösung umfasst '(8,10)' statt '(9,12)' im Beispiel? –
Die Mitglieder des Sets müssen sich überschneiden. Wenn nicht, würden sie nicht die ganze Bandbreite abdecken. Wenn wir also "(8, 10)" einschließen, müsste es noch "(9, 12)" enthalten. Wenn wir das aber tun würden, wäre es eine Menge der Größe 4 und nicht der Größe 3. Es ist also nicht mehr der kleinste mögliche Bereich, der den Bereich '(3, 13)' abdeckt. – Ephraim