Längste subarray, deren Elemente bilden eine kontinuierliche Abfolge
Gegeben ein unsortierter array von positiven ganzen zahlen, die Länge der längsten subarray, deren Elemente, wenn Sie sortiert sind kontinuierlich. Können Sie sich vorstellen wie ein O(n) Lösung?
Beispiel:
{10, 5, 3, 1, 4, 2, 8, 7}, Antwort ist 5.
{4, 5, 1, 5, 7, 6, 8, 4, 1}, Antwort ist 5.
Für das erste Beispiel, das subarray {5, 3, 1, 4, 2} wenn sortiert werden kann, bilden eine kontinuierliche Folge 1,2,3,4,5, die die längste.
Für das zweite Beispiel, das subarray {5, 7, 6, 8, 4} ist das Ergebnis subarray.
Ich denken kann, eine Methode, die für jedes subarray, überprüfen Sie, ob (maximum - minimum + 1) ist gleich der Länge des subarray, wenn das stimmt, dann ist es eine kontinuierliche subarray. Nehmen Sie die längste von allen. Aber es ist O(n^2) und nicht umgehen können mit Duplikaten.
Kann jemand gibt eine bessere Methode?
- Dürfen Sie zum ändern der array? Wie viel zusätzlicher Speicherplatz zur Verfügung steht?
- Sie haben keine Gründe zu glauben, es gibt eine O(n) Lösung? (+1)
- Eigentlich ist es eine interview-Frage.
- Keinen Platz begrenzen.
- Was sind die Einschränkungen für die Werte der ganzen zahlen im array? Wenn es keine, ich würde Wetten auf: es ist unmöglich zu tun, dass die Komplexität in weniger als
O(n*log(n))
- Ich denke, wir sollten einige Umsetzung-stapeln oder/und in Warteschlangen zu speichern, die max-min-Elemente von subarray. Dies ist ein gängiger Ansatz für O(n) algorithmen mit arrays und subarrays
- Positiv, keine weiteren Einschränkungen.
- Welche Annahmen sind zulässig in Bezug auf Duplikate? Ist es sicher, anzunehmen, dass jede ganze Zahl tritt höchstens einmal?
- Es kann ganze zahlen mehr als einmal vorkommen. Ich habe den Beitrag editieren zu geben noch ein Beispiel für Dubletten.
- Können Sie bitte definieren Sie "subarray"? Muss es zusammenhängend in das original-array?
- Ich denke, es muss zusammenhängend sein, wie vorgeschlagen, durch das Beispiel mit den Duplikaten
- Ist ein subarray, das Duplikate enthält, erlaubt? E. g. für die Eingabe
3 1 1 2 5
können wir ein subarray von der Länge 41 1 2 3
? - Nein, die Antwort für dein Beispiel wäre 2 für die subarray {1, 2}
Du musst angemeldet sein, um einen Kommentar abzugeben.
Algorithmus zum lösen ursprüngliche problem in O(n) ohne Duplikate. Vielleicht hilft es jemandem, der Entwicklung in O(n) Lösung, die sich mit Duplikaten.
Eingabe: [a1, a2, a3, ...]
Karte original-array als paar, wo 1. element ist ein Wert, und 2. ist der index des array.
Array: [[a1, i1], [a2, i2], [a3, i3], ...]
Sortieren das array von Paaren mit einigen O(n) Algorithmus (e.g Zählen, Sortieren) für integer-Sortierung von Wert.
Wir haben hier einige ein anderes array:
Array: [[a3, i3], [a2, i2], [a1, i1], ...]
wo a3, a2, a1, ... sind in sortierter Reihenfolge.
Ausführen Schleife über sortierte array von Paaren
In der linearen Zeit, die wir erkennen können aufeinander folgende Gruppen von zahlen, a3, a2, a1. Aufeinanderfolgende Gruppe definition ist der nächste Wert = prev-Wert + 1.
Beim Scannen halten Sie die aktuelle Größe der Gruppe (n), mindestens ein Wert von index (min), und die aktuelle Summe der Indizes (actualSum).
Auf jedem Schritt in aufeinander folgenden Gruppe können wir schätzen die Summe der Indizes, denn Sie schaffen arithmetische progression mit dem ersten element min, Schritt 1, und die Größe der Gruppe bisher gesehen n.
Diese Summe schätzen kann durchgeführt werden in O(1) Zeit mit Hilfe der Formel für die arithmetische progression:
Schätzung Summe = (a1 + an) * n /2;
Schätzung Summe = (min + min + (n - 1)) * n /2;
Schätzung Summe = min * n + n * (n - 1) /2;
Wenn auf einigen Schleife in Schritt aufeinander folgenden Gruppe Schätzung Summe entspricht der tatsächlichen Summe, dann bisher gesehen aufeinanderfolgende Gruppe, die diese Bedingungen erfüllen. Speichern n als aktuelle maximale Ergebnis, oder wählen Sie maximal zwischen aktuellen, maximalen und n.
Wenn auf der Wert-Elemente wir aufhören, aufeinander folgenden Gruppe, dann setzen Sie alle Werte und das gleiche tun.
Code Beispiel: https://gist.github.com/mishadoff/5371821
max - min + 1 == n
statt. Der code verwendetO(n*log(n))
Sortieren. Es ist nicht klar, wie Sortieren von ganzen zahlen inO(n)
wenn es keine Obere Grenze für Integer z.B., wenn essqrt(n)
vonn**sqrt(n)
Ganzzahlen, dann ist die input-Größe ist nochO(n)
aber Counting Sort istO(n + maxdiff) = O(n + n**sqrt(n)) = O(n**sqrt(n))
oder Radix-Sort istO(n*ndigits) = O(n * sqrt(n))
. Ich benutze Computer-Modell, dass hier davon ausgegangen, dassn
können gespeichert werden, inO(1)
Maschine Worten.O(n)
so dassmin(bin[j]) - max(bin[i]) > n
undmax(bin[i]) - min(bin[i])
istO(n)
. Und Suche für "kontinuierliche Abfolgen" innerhalb der einzelnen bins. Es führen könnte, zuO(n)
Algorithmus für die Eingabe ohne Duplikate.Sehen, wird das Feld S in seiner mathematischen definition :
Wo die Ij disjunkt sind integer-Segmente. Sie können ein bestimmtes Intervall-Baum (basierend auf einem Rot-Schwarz-Baum oder ein self-balancing tree, die Sie mögen 🙂 ) zu speichern, das array im mathematischen Definitionen. Die Knoten und Baum-Strukturen, die Aussehen sollte wie diese :
Hier, d ist die kleinere Grenze des integer-segment und u die Obere Schranke.
count
Hinzugefügt wird, um zu nehmen Pflege von möglichen Dubletten im array : beim Versuch, fügen Sie ein bereits vorhandenes element in den Baum, anstatt nichts zu tun, wir erhöhen dencount
Wert des Knotens, in dem es gefunden wird.Den Baum speichern nur disjunkte Knoten, so dass das einsetzen ist ein wenig komplexer als eine klassische Rot-Schwarz-Baum einfügen. Beim einfügen von Abständen, müssen Sie die scans auf mögliche überläufe mit bereits bestehenden Intervalle. In Ihrem Fall, da Sie nur einfügen singletons dies sollte nicht zu viel overhead.
Drei Knoten P, L und R, L wird der linke Kind von P und R das Rechte Kind von P. Dann ist, müssen Sie erzwingen, L. u < P. d und P. u < R. d (und für jeden Knoten, d <= u, natürlich).
Beim einfügen eines ganzzahligen segment [x,y], müssen Sie die "überlappung" - Segmenten, das heißt, die Intervalle [u,d] erfüllt, dass eine der folgenden Ungleichungen :
Wenn die eingelegte Intervall ist ein singleton
x
, dann können Sie nur finden bis zu 2 überlappende Intervall Knoten N1 und N2, so dassN1.d == x + 1
undN2.u == x - 1
. Dann haben Sie die Zusammenführung der beiden Intervalle und update zu zählen, die Sie Blätter mit N3, so dassN3.d = N2.d
,N3.u = N1.u
undN3.count = N1.count + N2.count + 1
. Da das delta zwischenN1.d
undN2.u
ist das minimale delta für die zwei Segmente werden disjunkt, dann sind Sie muss haben eine der folgenden :Damit Sie die Einfügemarke noch in
O(log(n))
im schlimmsten Fall.Von hier aus kann ich nicht herausfinden, wie zu handhaben die Ordnung in der ersten Folge, aber hier ist ein Ergebnis, das interessant sein könnte : wenn das Eingabe-array definiert einen perfekte integer-segment, dann wird der Baum hat nur einen Knoten.
UPD2: Die folgende Lösung für ein problem, wenn es nicht erforderlich ist, dass subarray ist zusammenhängend. Habe ich falsch verstanden, die problem-Anweisung. Nicht löschen diese, wie jemand möglicherweise eine Idee, basierend auf der mine, die die Arbeit für das eigentliche problem.
Hier ist, was ich mir ausgedacht habe:
Erstellen Sie eine Instanz des dictionary (implementiert als hash-Tabelle, was O(1) in normalen Situationen). Die Schlüssel sind ganze zahlen, sind die Werte hash-sets der zahlen (auch O(1)) –
var D = new Dictionary<int, HashSet<int>>
.Iteration durch das array
A
und für jede ganze Zahln
mit indexi
tun:n-1
undn+1
enthalten sind inD
.D.Add(n, new HashSet<int>)
n-1
tunD.Add(n, D[n-1])
D[n-1].UnionWith(D[n+1]); D[n+1] = D[n] = D[n-1];
D[n].Add(n)
Gehen Sie nun durch die einzelnen Schlüssel in
D
und finden Sie die hash-set mit der größten Länge (Suche nach Länge O(1)). Die größte Länge wird die Antwort sein.Meinem Verständnis, die schlimmsten Fall Komplexität O(n*log(n)), nur weil der
UnionWith
Betrieb. Ich weiß nicht, wie die Berechnung der durchschnittlichen Komplexität, aber es sollte in der Nähe der O(n). Bitte korrigieren Sie mich, wenn ich falsch bin.UPD: Zu sprechen-code, hier ist eine test-Implementierung in C#, das gibt das richtige Ergebnis in den beiden OP ' s Beispiele:
[10, 5, 3, 1, 4, 2, 8, 7, 0]
sollte5
, die maximale subarray ist[5, 3, 1, 4, 2]
. Die zusätzliche0
am Ende nicht verändern! Aber dein code gibt das Ergebnis zurück6
, als es annimmt, das element0
Teil der (nicht-zusammenhängend!) maximale subarray.[4, 5, 1, 5, 7, 6, 8, 4, 1]
wäre7
statt5
wenn nicht-benachbart durften. Außerdem wird die Anzahl der möglichen Teilmengen wären2^n
stattn^2
.Dies erfordert zwei Durchläufe über die Daten. Zuerst erstellen Sie eine hash-map, mapping-ints zu bools. Ich aktualisierte meinen Algorithmus nicht zu verwenden, anzeigen, aus der STL, die ich bin, positiv verwendet die Sortierung intern. Dieser Algorithmus verwendet hashing und problemlos aktualisiert werden kann, für jede maximale oder minimale Kombination, möglicherweise sogar alle möglichen Werte, die ein integer erhalten.
Die Grundidee ist es, die hash-map als einen Eimer Sortieren, so dass Sie nur zwei Durchgänge über die Daten. Dieser Algorithmus ist O(2n), die wiederum O(n)
Nicht Ihre Hoffnungen, dies ist nur eine unvollständige Antwort.
Ich bin mir ziemlich sicher, dass das problem nicht lösbar in
O(n)
. Leider kann ich nicht beweisen.Wenn es gibt einen Weg, um es zu lösen in weniger als
O(n^2)
ist, würde ich vermuten, dass die Lösung basiert auf folgender Strategie:O(n)
(oder vielleichtO(n log n)
), ob es existiert eine kontinuierliche subarray wie du es beschreibst mit mindestensi
Elemente. Nennen wir dieses PrädikatE(i)
.i
für dieE(i)
hält.Die Gesamtlaufzeit dieses Algorithmus wäre dann
O(n log n)
(oderO(n log^2 n)
).Dies ist der einzige Weg, ich könnte kommen mit, um zu reduzieren das problem auf ein anderes problem, dass hat zumindest das potential, einfacher als die ursprüngliche Formulierung. Allerdings konnte ich nicht einen Weg finden, um zu berechnen
E(i)
in weniger alsO(n^2)
, so kann ich Sie komplett ausschalten...hier ist ein weiterer Weg, zu denken, Ihr problem: angenommen Sie haben ein array setzt sich nur aus 1en und 0EN, die Sie wollen, zu finden, die längste aufeinanderfolgenden ausführen von 1s. dies kann in linearer Zeit durch run-length-encoding 1s (ignorieren Sie die 0 ist). damit verwandeln Sie Ihren ursprünglichen problem in diesem neuen run-length-encoding problem, Sie berechnen ein neues array b[i] = (a[i] < a[i+1]). dies muss nicht explizit gemacht, können Sie tun es einfach implizit zu erreichen, einen Algorithmus mit konstanter Speicherbedarf und die lineare Komplexität.
Hier sind 3 sinnvolle Lösungen:
Die erste ist
O(nlog(n))
im Zeit-undO(n)
Raum, das zweite istO(n)
im Zeit-undO(n)
im Raum, und die Dritte istO(n)
im Zeit-undO(1)
im Raum.bauen
binary search tree
dann durchqueren es um.halten Sie 2 Zeiger, einen für den start von max Teilmenge und eine für das Ende.
halten Sie die
max_size
Wert während der Iteration der Struktur.es ist ein
O(n*log(n))
Zeit und Raum Komplexität.kann man immer Sortieren, zahlen-set mit zählen, Sortieren in einer linearen Zeit
und nach dem Durchlauf durch das array, was bedeutet, dass
O(n)
Zeit und Raumdie Komplexität.
Vorausgesetzt, es ist nicht überlaufen oder einen großen ganzzahligen Datentyp. Vorausgesetzt das array ist ein mathematischer Satz (keine doppelten Werte). Sie können es in
O(1)
Speicher:O(n)
Zeit Komplexität.min
,max
,size
sind genug.