Von meinem Kommentar ursprünglich: Dies ist eng mit einer Menge allgegenwärtig in der akademischen Produktivität Beurteilung im Zusammenhang, der Hirsh Index besser bekannt als die -Indexh . Kurz gesagt ist es , wenn die Anzahl von Publikationen definiert man hat , so dass jede von ihnen hat zumindest h Zitierungen (die größte derartige h ).hhh
Der einzige Unterschied zwischen Ihnen und Ihrem Problem besteht darin, dass Sie sich nicht nur dafür interessieren, wie viele Veröffentlichungen das Kriterium erfüllen, sondern auch, wie oft sie zitiert werden. Dies ist jedoch eine geringfügige Änderung. Die Daten sind schon da, der ursprüngliche Algorithmus lässt sie einfach fallen.
Die allgemein umgesetzte Berechnung ist eher unkompliziert und stimmt mit der Antwort von Karolis Juodelė überein .
Update: Abhängig von der Größe und dem Charakter Ihrer Daten kann es sich lohnen, Methoden zu untersuchen, die das Array teilweise sortieren, indem Daten über und unter einem Dreh- und Angelpunkt gefiltert werden (QuickSort fällt ein). Dann, je nachdem, ob zu wenig oder zu viele vorhanden sind, passen Sie den Drehpunkt an und wiederholen Sie den Vorgang für die Teilmenge, die ihn enthält, und so weiter. Sie brauchen keine Reihenfolge zwischen Elementen, die höher als , und schon gar nicht zwischen denen, die niedriger als h sind. Wenn Sie zum Beispiel alle Elemente gefunden haben, die größer oder gleich h 1 sind und von denen es weniger als h 1 gibt , müssen Sie diese Untergruppe nicht erneut berühren, sondern nur hinzufügen. Dadurch wird die inhärente Rekursion in eine Endrekursion umgewandelt und kann somit als Schleife umgeschrieben werden.hh1h1
Mein Haskell ist ein bisschen rostig, aber dies sollte das tun, was ich oben beschrieben habe und scheint zu funktionieren. Hoffe, es kann bis zu einem gewissen Grad verstanden werden, ich freue mich, weitere Erklärungen zu geben.
-- just a utility function
merge :: [a] -> [a] -> [a]
merge [] ys = ys
merge (x:xs) ys = x : merge xs ys
-- the actual implementation
topImpl :: [Int] -> [Int] -> [Int]
topImpl [] granted = granted
topImpl (x:xs) granted
| x == (1 + lGreater + lGranted) = x : merge greater granted
| x > (1 + lGreater + lGranted) = topImpl smaller (x : merge greater granted)
| otherwise = topImpl greater granted
where smaller = [y | y <- xs, y < x]
greater = [y | y <- xs, y >= x]
lGreater = length greater
lGranted = length granted
-- starting point is: top of whole array, granted is empty
top :: [Int] -> [Int]
top arr = topImpl arr []
Die Idee ist, in dem, granted
was Sie wissen, zu sammeln , dass es definitiv zum Ergebnis beiträgt, und es nicht weiter zu sortieren. Wenn greater
zusammen mit x
passt, haben wir Glück, sonst müssen wir mit einer kleineren Teilmenge versuchen. (Der Zapfen x
ist einfach , was passiert ist das erste Element der Unterliste sein , die derzeit in Betracht gezogen wird .) Beachten Sie, dass der wesentliche Vorteil gegenüber Einnahme größten Elemente eines nach dem anderen ist , dass wir dies tun auf Blöcke von durchschnittlicher Größe und müssen nicht weiter sortiert werden.r e m a i n i n g/ 2
Beispiel:
Lass uns dein Set nehmen [1,3,4,1,3,6]
.
x = 1
, granted = []
, greater = [3,4,1,3,6]
. Autsch, wir treffen einen pathologischen Fall, wenn der Drehzapfen smaller
direkt im ersten Schritt zu klein ist (tatsächlich so klein, dass er leer ist). Zum Glück ist unser Algo dazu bereit. Es verwirft x
und versucht es erneut mit greater
allein.
x = 3
, granted = []
, greater = [4,3,6]
. Zusammen bilden sie ein Array der Länge 4, aber wir haben nur das von unten auf 3 begrenzt, das ist also zu viel. Wiederholen Sie auf greater
allein.
x = 4
, granted = []
, greater = [6]
. Dies ergibt ein Array von 2 Elementen ≥ 4, anscheinend haben wir für einige mehr davon Verwendung. Behalte dies bei und wiederhole es smaller = [3]
.
x = 3
, granted = [4,6]
, greater = []
. Dies ergibt zusammen ein Array von 3 Elementen ≥ 3, sodass wir unsere Lösung haben [3,4,6]
und zurückkehren können. (Beachten Sie, dass die Permutation abhängig von der Reihenfolge der Eingabe variieren kann, aber immer die höchstmöglichen Terme enthält, niemals [3,3,6]
oder [3,3,4]
für Ihr Beispiel.)
(Übrigens ist zu beachten, dass die Rekursion tatsächlich nur zu einem Zyklus zusammengebrochen ist.) Die Komplexität ist aufgrund der vielen gespeicherten Vergleiche etwas besser als Quicksort:
n - 1
O ( logn )O ( n )
nO ( n2)
Es gibt ein paar unnötige Vergleiche im obigen Code, wie die Berechnung, smaller
ob wir es brauchen oder nicht, sie können leicht entfernt werden. (Ich denke, dass eine faule Bewertung dies jedoch erledigen wird.)