Ich habe ein algorithmisches Problem.
Beispielsweise:
- Wenn = [1, 3, 4, 1, 3, 6] ist, kann [3, 3, 6] oder [3, 4, 6] oder [4, 3, 6] sein.
- In = [7, 5, 1, 1, 7, 4] ist [7, 5, 7, 4].
Ich habe diese rekursive Funktion ausprobiert.
function(T):
if minimum(T) >= length(T):
return T
else:
return function(T\minimum(T))
Gibt es einen nicht-rekursiven Algorithmus? (Ich habe meinen rekursiven Algorithmus nicht überprüft, damit er einen Fehler aufweist.)
algorithms
optimization
sets
drzbir
quelle
quelle
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 ).h h h
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.h h1 h1
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.
Die Idee ist, in dem,r e m a i n i n g/ 2
granted
was Sie wissen, zu sammeln , dass es definitiv zum Ergebnis beiträgt, und es nicht weiter zu sortieren. Wenngreater
zusammen mitx
passt, haben wir Glück, sonst müssen wir mit einer kleineren Teilmenge versuchen. (Der Zapfenx
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.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 Drehzapfensmaller
direkt im ersten Schritt zu klein ist (tatsächlich so klein, dass er leer ist). Zum Glück ist unser Algo dazu bereit. Es verwirftx
und versucht es erneut mitgreater
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 aufgreater
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 essmaller = [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:
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.)quelle
An Ihrem Algorithmus ist nichts auszusetzen, und natürlich können die meisten rekursiven Algorithmen in Schleifen konvertiert werden, hier eine Schleifenversion Ihres rekursiven Codes:
quelle
Jeder rekursive Algorithmus kann zur Verwendung der Iteration umgeschrieben werden. Schließlich weiß eine Turing-Maschine nichts über Rekursion, kann aber jeden Algorithmus implementieren. Im Prinzip können Sie Ihre rekursive Funktion umschreiben, indem Sie Ihren eigenen Stapelmanipulationscode schreiben, um sich die Werte der Funktionsparameter und etwaiger lokaler Variablen zu merken. In diesem speziellen Fall ist Ihre Funktion rekursiv (sobald ein rekursiver Aufruf zurückkehrt, kehrt auch das Objekt, das sie aufgerufen hat, sofort zurück), sodass Sie den Stack nicht einmal warten müssen.
quelle
Verwenden Sie einen Min-Heap, um eine Teil-Heap-Sortierung durchzuführen, da nicht das gesamte Array sortiert werden muss.
Knallen Sie die Elemente so lange, bis Sie den angegebenen Schwellenwert überschreiten.
quelle