Ich habe einen Code gefunden, den ich vor einigen Monaten für die Vorbereitung eines Interviews geschrieben habe.
Nach dem Kommentar, den ich hatte, wurde versucht, dieses Problem zu lösen:
Suchen Sie bei einem bestimmten Dollarwert in Cent (z. B. 200 = 2 Dollar, 1000 = 10 Dollar) alle Kombinationen von Münzen, aus denen der Dollarwert besteht. Es sind nur Pennys (1 ¢), Nickel (5 ¢), Groschen (10 ¢) und Viertel (25 ¢) zulässig.
Wenn beispielsweise 100 angegeben wurde, sollte die Antwort lauten:
4 quarter(s) 0 dime(s) 0 nickel(s) 0 pennies
3 quarter(s) 1 dime(s) 0 nickel(s) 15 pennies
etc.
Ich glaube, dass dies sowohl iterativ als auch rekursiv gelöst werden kann. Meine rekursive Lösung ist ziemlich fehlerhaft, und ich habe mich gefragt, wie andere Leute dieses Problem lösen würden. Der schwierige Teil dieses Problems bestand darin, es so effizient wie möglich zu gestalten.
quelle
code-golf
=> stackoverflow.com/questions/tagged/code-golfAntworten:
Ich habe mich vor langer Zeit einmal damit befasst, und Sie können meine kleine Beschreibung darüber lesen . Hier ist die Mathematica-Quelle .
Durch die Verwendung von Generierungsfunktionen können Sie eine zeitlich konstante Lösung des Problems in geschlossener Form erhalten. Graham, Knuth und Patashniks Concrete Mathematics ist das Buch dafür und enthält eine ziemlich ausführliche Diskussion des Problems. Im Wesentlichen definieren Sie ein Polynom, bei dem der n- te Koeffizient die Anzahl der Änderungsmöglichkeiten für n Dollar ist.
Die Seiten 4 bis 5 der Beschreibung zeigen, wie Sie Mathematica (oder ein anderes praktisches Computeralgebrasystem) verwenden können, um die Antwort für 10 ^ 10 ^ 6 Dollar in wenigen Sekunden in drei Codezeilen zu berechnen.
(Und das war lange genug her, dass das auf einem 75-MHz-Pentium ein paar Sekunden sind ...)
quelle
a
als die Domäne vonf
abera = {1,5,10,25,50,100}
. Es sollte eine 5- in der Cent-Münzenliste geben. Ansonsten war das Schreiben fantastisch, danke!Hinweis : Hier wird nur die Anzahl der Möglichkeiten angezeigt.
Scala-Funktion:
quelle
n1 * coins(0) + n2 * coins(1) + ... + nN * coins(N-1) = money
. Also fürmoney=0
undcoins=List(1,2,5,10)
die Anzahl für Kombinationen(n1, n2, n3, n4)
ist 1 und die Lösung ist(0, 0, 0, 0)
.money == 0
dochcoins.isEmpty
, sollte es nicht als Sol'n gelten. Daher kann der Algo besser bedient werden, wenn diecoins.isEmpty || money < 0
Bedingung zuerst geprüft wird.Ich würde eine rekursive Lösung bevorzugen. Sie haben eine Liste von Stückelungen. Wenn die kleinste den verbleibenden Währungsbetrag gleichmäßig aufteilen kann, sollte dies gut funktionieren.
Grundsätzlich wechseln Sie vom größten zum kleinsten Nennwert.
Rekursiv,
Hier ist meine Python-Version Ihres angegebenen Problems für 200 Cent. Ich bekomme 1463 Wege. Diese Version druckt alle Kombinationen und die endgültige Zählsumme.
quelle
denominations
nicht1
den letzten Wert hat. Sie können dem innerstenif
Block eine kleine Menge Code hinzufügen, um das Problem zu beheben (wie in meiner Antwort auf die andere Frage beschrieben).Scala-Funktion:
quelle
Hier ist ein absolut unkomplizierter C ++ - Code zur Lösung des Problems, bei dem alle Kombinationen angezeigt werden mussten.
Aber ich bin ziemlich fasziniert von dem Unterproblem, nur die Anzahl der Kombinationen zu berechnen. Ich vermute, es gibt eine geschlossene Gleichung dafür.
quelle
Das Unterproblem ist ein typisches Problem der dynamischen Programmierung.
quelle
Der Code verwendet Java, um dieses Problem zu lösen, und es funktioniert auch ... Diese Methode ist möglicherweise wegen zu vieler Schleifen keine gute Idee, aber es ist wirklich ein einfacher Weg.
quelle
Dies ist eine wirklich alte Frage, aber ich habe eine rekursive Lösung in Java gefunden, die kleiner zu sein schien als alle anderen.
Verbesserungen:
quelle
Sei C (i, J) die Menge der Kombinationen von i Cent unter Verwendung der Werte in der Menge J.
Sie können C wie folgt definieren:
(first (J) nimmt deterministisch ein Element einer Menge auf)
Es stellt sich als ziemlich rekursive Funktion heraus ... und ziemlich effizient, wenn Sie Memoization verwenden;)
quelle
Semi-Hack, um das einzigartige Kombinationsproblem zu umgehen - absteigende Reihenfolge erzwingen:
Dies läuft langsam, da es nicht gespeichert wird, aber Sie bekommen die Idee.
quelle
quelle
Dies ist meine Antwort in Python. Es wird keine Rekursion verwendet:
Beispielausgabe
quelle
quelle
Beide: Durchlaufen Sie alle Nennwerte von hoch nach niedrig, nehmen Sie einen Nennwert, subtrahieren Sie von der erforderlichen Summe und wiederholen Sie den Rest (wobei die verfügbaren Nennwerte auf den aktuellen Iterationswert gleich oder niedriger sein müssen).
quelle
Wenn das Währungssystem dies zulässt, ein einfacher gieriger Algorithmus , der so viele Münzen wie möglich nimmt, beginnend mit der Währung mit dem höchsten Wert.
Andernfalls ist eine dynamische Programmierung erforderlich, um schnell eine optimale Lösung zu finden, da dieses Problem im Wesentlichen das Rucksackproblem ist .
Wenn zum Beispiel ein Währungssystem die Münzen
{13, 8, 1}
hat:, würde die gierige Lösung eine Änderung für 24 as vornehmen{13, 8, 1, 1, 1}
, aber die wirklich optimale Lösung ist{8, 8, 8}
Bearbeiten: Ich dachte, wir würden Änderungen optimal vornehmen und nicht alle Möglichkeiten auflisten, um Änderungen für einen Dollar vorzunehmen. In meinem letzten Interview wurde gefragt, wie ich etwas ändern soll, also sprang ich voran, bevor ich mit dem Lesen der Frage fertig war.
quelle
Ich weiß, dass dies eine sehr alte Frage ist. Ich habe nach der richtigen Antwort gesucht und konnte nichts finden, was einfach und zufriedenstellend ist. Ich habe einige Zeit gebraucht, konnte aber etwas aufschreiben.
Dies ist eine Javascript-Lösung und verwendet Rekursion.
quelle
In der Programmiersprache Scala würde ich das so machen:
quelle
Dies ist ein einfacher rekursiver Algorithmus, der eine Rechnung nimmt, dann eine kleinere Rechnung rekursiv nimmt, bis sie die Summe erreicht, dann eine andere Rechnung mit demselben Nennwert nimmt und erneut rekursiert. Zur Veranschaulichung siehe Beispielausgabe unten.
Druckt Folgendes:
quelle
Duh, ich fühle mich gerade dumm. Unten gibt es eine übermäßig komplizierte Lösung, die ich erhalten werde , weil es ist eine Lösung, nachdem alle. Eine einfache Lösung wäre folgende:
Hier ist die andere Lösung. Diese Lösung basiert auf der Beobachtung, dass jede Münze ein Vielfaches der anderen ist, sodass sie in Bezug auf sie dargestellt werden können.
Also für 37 Münzen zum Beispiel:
quelle
Dieser Blogeintrag von mir löst dieses rucksackartige Problem für die Figuren aus einem XKCD-Comic . Eine einfache Änderung des
items
Diktats und desexactcost
Werts liefert auch alle Lösungen für Ihr Problem.Wenn das Problem darin besteht, die Änderung zu finden, die die geringsten Kosten verursacht, kann ein naiver, gieriger Algorithmus, der so viel wie möglich von der Münze mit dem höchsten Wert verwendet, bei einigen Kombinationen von Münzen und Zielbetrag fehlschlagen. Zum Beispiel, wenn es Münzen mit den Werten 1, 3 und 4 gibt; und der Zielbetrag ist 6, dann schlägt der gierige Algorithmus möglicherweise drei Münzen mit den Werten 4, 1 und 1 vor, wenn leicht zu erkennen ist, dass Sie jeweils zwei Münzen mit dem Wert 3 verwenden können.
quelle
quelle
Ich habe diesen ordentlichen Code in dem Buch "Python For Data Analysis" von O'reily gefunden. Es verwendet eine verzögerte Implementierung und einen int-Vergleich und ich nehme an, dass es mit Dezimalstellen für andere Nennwerte geändert werden kann. Lassen Sie mich wissen, wie es bei Ihnen funktioniert!
quelle
Dies ist die Verbesserung von Zihans Antwort. Die vielen unnötigen Schleifen entstehen, wenn der Nennwert nur 1 Cent beträgt.
Es ist intuitiv und nicht rekursiv.
quelle
Einfache Java-Lösung:
quelle
quelle
Hier ist eine C # -Funktion:
Verwenden Sie es so:
Es druckt:
quelle
Unten finden Sie ein Python-Programm, mit dem Sie alle Geldkombinationen finden können. Dies ist eine dynamische Programmierlösung mit Auftragszeit (n). Geld ist 1,5,10,25
Wir wechseln von Zeilengeld 1 zu Zeilengeld 25 (4 Zeilen). Zeilengeld 1 enthält die Anzahl, wenn wir bei der Berechnung der Anzahl der Kombinationen nur Geld 1 berücksichtigen. Zeilengeld 5 erzeugt jede Spalte, indem die Zählung in Zeilengeld r für dasselbe Endgeld plus die vorherigen 5 Zählungen in der eigenen Zeile (aktuelle Position minus 5) vorgenommen wird. Zeilengeld 10 verwendet Zeilengeld 5, das Zählungen für beide 1,5 enthält und die vorherigen 10 Zählungen addiert (aktuelle Position minus 10). Zeilengeld 25 verwendet Zeilengeld 10, das Zählungen für Zeilengeld 1,5,10 plus die vorherigen 25 Zählungen enthält.
Zum Beispiel Zahlen [1] [12] = Zahlen [0] [12] + Zahlen [1] [7] (7 = 12-5), was zu 3 = 1 + 2 führt; Zahlen [3] [12] = Zahlen [2] [12] + Zahlen [3] [9] (-13 = 12-25), was zu 4 = 0 + 4 führt, da -13 kleiner als 0 ist.
quelle
Java-Lösung
}}
quelle
Die folgende Java-Lösung, die auch die verschiedenen Kombinationen druckt. Einfach zu verstehen. Idee ist
für Summe 5
Die Lösung ist
Wenn die verbleibende Summe in jeder Schleife kleiner als der Nennwert ist, dh wenn die verbleibende Summe 1 kleiner als 2 ist, brechen Sie einfach die Schleife
Der vollständige Code unten
Bitte korrigieren Sie mich im Fehlerfall
}}
quelle
Hier ist eine Python-basierte Lösung, die sowohl Rekursion als auch Memoisierung verwendet, was zu einer Komplexität von O (mxn) führt.
quelle