Das Finden der N-ten größten Wert in einer Gruppe von Zahlen, wie sie erzeugt werden,

StackOverflow https://stackoverflow.com/questions/1084365

  •  23-08-2019
  •  | 
  •  

Frage

Ich schreibe ein Programm als Bedarf an den N-ten größten Wert in einer Gruppe von Zahlen zu finden. Diese Zahlen werden durch das Programm erzeugt, aber ich habe nicht genug Speicher N-Nummern zu speichern. Gibt es eine bessere obere Schranke als N, die für die Lagerung acheived werden kann? Die obere Grenze für die Größe der Gruppe von Nummern (und für N) etwa 100.000.000.

. Hinweis: Die Zahlen sind Dezimalzahlen und die Liste kann Duplikate enthalten

[Bearbeiten]. Mein Speicherlimit ist 16 MB

War es hilfreich?

Lösung

Dies ist ein Multipass-Algorithmus (also müssen Sie in der Lage sein, die gleiche Liste mehrere Male zu erzeugen, oder speichern Sie die Liste aus den Sekundärspeicher).

Erster Durchgang:

  • Den höchsten Wert und dem niedrigsten Wert. Das ist Ihr erster Bereich.

Pässe nach dem ersten:

  1. Dividieren Bereich bis in 10 gleich beabstandeten Bins. Wir brauchen nicht in den Behältern keine Zahlen zu speichern. Wir werden nur die Mitgliedschaft in den Fächern zählen. So haben wir gerade eine Reihe von ganzen Zahlen (oder bigints - was auch immer in unsere Zahlen genau halten kann) Beachten Sie, dass 10 ist eine willkürliche Wahl für die Anzahl der Bins. Ihre Stichprobengröße und Verteilung bestimmen die beste Wahl.
  2. Spin durch jede Zahl in den Daten, die Anzahl der je nachdem, was ist Inkrementieren hält die Nummer, die Sie sehen.
  3. Herauszufinden, welche sind Ihre Antwort hat, und fügen Sie, wie viele Zahlen über diesem Behälter, um eine Anzahl von Zahlen über dem Gewinn ist sind.
  4. Die Sieger sind die obere und unterer Bereich ist Ihr neuer Bereich.
  5. Schleife durch diese Schritte wieder, bis Sie genug Speicher haben die Zahlen im aktuellen bin zu halten.

Letzter Pass:

  • Sie sollten wissen, wie viele Zahlen über dem aktuellen bin sind jetzt.
  • Sie haben genügend Speicher alle Zahlen in Ihrem Bereich des aktuellen bin zu greifen, so können Sie drehen durch und die tatsächlichen Zahlen greifen. sortieren sie einfach und die richtige Nummer greifen.

Beispiel: Wenn der Bereich, den Sie sehen 0.0 bis 1000.0 ist, werden Ihr Bins' Bereiche liegen:

 (- 0.0 - 100.0]
 (100.0 - 200.0]
 (200.0 - 300.0]
 ...
 (900.0 - 1000.0)

Wenn Sie durch die Zählungen, die Ihre Zahl ist in dem (100,0 bis 2000,0] sind, Ihr nächster Satz von Bins werden:

 (100.0 - 110.0]
 (110.0 - 120.0]
 etc.

Eine weitere Mehrweg-Idee:

Einfach eine binäre Suche. Wählen Sie den Mittelpunkt des Bereichs als die erste Vermutung. Ihre Pässe brauchen nur eine oben / unten Zählung zu tun, um die nächste Schätzung zu bestimmen (die durch die Zählung gewichtet werden können, oder einen einfachen Durchschnitt Code Einfachheit).

Andere Tipps

Sind Sie in der Lage, die gleiche Gruppe von Zahlen von Anfang zu regenerieren? Wenn Sie sind, können Sie mehrere Durchgänge über den Ausgang machen. Starten, indem Sie den größten Wert zu finden, um den Generator neu zu starten, die größte Zahl kleiner als die finden, starten Sie den Generator, und wiederholen Sie dies, bis Sie Ihr Ergebnis haben

Es wird ein echten Performance-Killer sein, weil Sie eine Menge von Zahlen und eine Menge Pässe haben wird benötigt - aber Speicher-weise, Sie benötigen nur zwei Elemente speichern (das aktuelle Maximum und eine „Grenze“ , die Nummer, die Sie während des letzten Passes gefunden) und ein Rundenzähler.

Sie können es beschleunigen, indem Sie Ihre Prioritätswarteschlange mit den M größten Elemente (Auswahl einige M, die Sie in der Lage sind, in den Speicher zu passen) zu finden, so dass Sie die Anzahl der Durchgänge zu N / M reduzieren.

Wenn Sie finden müssen, sagen, das 10. größte Element in einer Liste von 15 Zahlen, könnten Sie Zeit durch die Arbeit umgekehrt speichern. Da es das 10. größte Element ist, das bedeutet, dass es 15-10 = 5 Elemente kleiner als dieses Element sind -. So könnten Sie stattdessen für die 6. kleinste Element aussehen

Dies ist vergleichbar mit einer anderen Frage - C-Programm n-te kleinstes Element in Array zu suchen, ohne Sortierung -?., wo Sie einige Antworten bekommen können
Die Logik wird für Nth größte / kleinste Suche auf ähnliche Weise arbeiten.
Hinweis:. Ich sage nicht, das ist ein Duplikat, dass


Da Sie viel (fast 1 Milliarde?) Haben Zahlen, hier ist eine weitere Möglichkeit für Raumoptimierung.
Nehmen wir an, Ihre Zahlen in 32-Bit-Werte passen, also etwa 1 Milliarde würde irgendwann der Nähe von 32 GB Platz benötigen. Nun, wenn Sie über 128 MB Arbeitsspeicher leisten können, können wir dies tun in einem Durchgang.

  1. Stellen Sie sich einen 1 Milliarde Bit-Vektor als ein Array von 32-Bit-Worten gespeichert
    • Lassen Sie es nur auf Nullen initialisiert werden
    • Starten Sie durch Ihre Zahlen laufen und halten Sie die richtige Bit-Position für den Wert der Zahl Einstellung
    • Wenn Sie mit einem Durchgang fertig sind, starten Sie von Anfang an diesem Bit-Vektor für den N-te Satz-Bit
    • Zählen
    • Position, die BITs gibt Ihnen den Wert für Ihre Nth größte Zahl
    • Sie haben alle tatsächlich sortiert die Zahlen in dem Verfahren (jedoch Anzahl der Duplikate wird nicht verfolgt)

Wenn ich gut verstanden, die obere Grenze der Speichernutzung für Ihr Programm ist O (N) (möglicherweise N + 1). Sie können eine Liste der erzeugten Werte halten, die größer ist als die aktuelle X (der N-ten größte Wert bisher) durch niedrigste zuerst bestellt. Sobald ein neuer Mehrwert generiert wird, können Sie die aktuellen X durch das erste Element der Liste ersetzen und den gerade generierten Wert an ihre entsprechenden Position in der Liste eingefügt werden.

sort -n | uniq -c und der N-te sollten die N-ten Zeile sein

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top