Я нашел фрагмент кода, который писал для подготовки к собеседованию несколько месяцев назад.
Согласно моему комментарию, он пытался решить эту проблему:
Учитывая некоторую долларовую стоимость в центах (например, 200 = 2 доллара, 1000 = 10 долларов), найдите все комбинации монет, которые составляют долларовую стоимость. Разрешены только пенни (1 цент), никель (5 центов), десять центов (10 центов) и четвертинки (25 центов).
Например, если дано 100, ответ должен быть таким:
4 quarter(s) 0 dime(s) 0 nickel(s) 0 pennies
3 quarter(s) 1 dime(s) 0 nickel(s) 15 pennies
etc.
Я считаю, что это можно решить как итеративным, так и рекурсивным способами. Мое рекурсивное решение довольно глючное, и мне было интересно, как другие люди решат эту проблему. Сложная часть этой проблемы заключалась в том, чтобы сделать ее максимально эффективной.
algorithm
recursion
puzzle
coin-change
codingbear
источник
источник
code-golf
=> stackoverflow.com/questions/tagged/code-golfОтветы:
Я изучал это однажды, давным-давно, и вы можете прочитать мою небольшую рецензию на это . Вот исходный код Mathematica .
Используя производящие функции, вы можете получить решение проблемы в закрытом виде с постоянным временем. Книга Грэма, Кнута и Паташника « Конкретная математика» предназначена для этого и содержит довольно обширное обсуждение проблемы. По сути, вы определяете многочлен, где n- й коэффициент - это количество способов внести сдачу на n долларов.
На страницах 4–5 описания показано, как с помощью Mathematica (или любой другой удобной системы компьютерной алгебры) вычислить ответ на сумму 10 ^ 10 ^ 6 долларов за пару секунд в трех строках кода.
(И это было достаточно давно, это пара секунд на Pentium 75 МГц ...)
источник
a
как область «f
но»a = {1,5,10,25,50,100}
. В списке монет должна быть 5 центов. В противном случае описание было фантастическим, спасибо!Примечание . Здесь показано только количество способов.
Функция Scala:
источник
n1 * coins(0) + n2 * coins(1) + ... + nN * coins(N-1) = money
. Таким образом, дляmoney=0
иcoins=List(1,2,5,10)
количество комбинаций(n1, n2, n3, n4)
равно 1, а решение равно(0, 0, 0, 0)
.money == 0
ноcoins.isEmpty
, это не должно считаться солнцем. Следовательно, алгоритм может быть лучше обслужен, еслиcoins.isEmpty || money < 0
сначала выполняется проверка условия.Я бы предпочел рекурсивное решение. У вас есть некоторый список номиналов, если наименьший из них может равномерно разделить оставшуюся сумму валюты, это должно работать нормально.
В основном вы переходите от самого большого к наименьшему номиналу.
Рекурсивный,
Вот моя версия вашей заявленной проблемы на Python за 200 центов. Получаю 1463 способа. В этой версии печатаются все комбинации и итоговая сумма.
источник
denominations
нет1
последнего значения. Вы можете добавить небольшой объем кода во внутреннийif
блок, чтобы исправить это (как я описываю в своем ответе на другой вопрос).Функция Scala:
источник
Вот какой-то абсолютно простой код на C ++ для решения проблемы, который требует, чтобы были показаны все комбинации.
Но меня очень заинтриговала подзадача - просто подсчет количества комбинаций. Я подозреваю, что для этого есть уравнение в закрытой форме.
источник
Подзадача - типичная проблема динамического программирования.
источник
Код использует Java для решения этой проблемы, и он также работает ... Этот метод может быть не очень хорошей идеей из-за слишком большого количества циклов, но это действительно простой способ.
источник
Это действительно старый вопрос, но я придумал рекурсивное решение на java, которое казалось меньше, чем все другие, так что вот -
Улучшения:
источник
Пусть C (i, J) набор комбинаций получения i центов с использованием значений из множества J.
Вы можете определить C так:
(сначала (J) детерминированно принимает элемент множества)
Получается довольно рекурсивная функция ... и достаточно эффективная, если вы используете мемоизацию;)
источник
полувак, чтобы обойти проблему уникальной комбинации - принудительный порядок убывания:
Это будет работать медленно, поскольку оно не будет запоминаться, но идею вы поняли.
источник
источник
Это мой ответ на Python. Он не использует рекурсию:
Пример вывода
источник
источник
Оба: выполнить итерацию по всем номиналам от большего к меньшему, взять одно из номиналов, вычесть из требуемой суммы, затем выполнить рекурсию по остатку (ограничение доступных номиналов равным или меньшим текущему значению итерации).
источник
Если это позволяет валютная система, простой жадный алгоритм который берет как можно больше каждой монеты, начиная с валюты самой высокой стоимости.
В противном случае требуется динамическое программирование, чтобы быстро найти оптимальное решение, поскольку эта проблема, по сути, является проблемой ранца .
Например, если в валютной системе есть монеты:,
{13, 8, 1}
жадное решение внесет изменение на 24 as{13, 8, 1, 1, 1}
, но истинное оптимальное решение -{8, 8, 8}
Изменить: я думал, что мы вносим изменения оптимально, не перечисляя все способы внести изменения за доллар. В моем недавнем интервью меня спрашивали, как внести изменения, поэтому я сразу перескочил вперед, чтобы прочитать вопрос.
источник
Я знаю, что это очень старый вопрос. Я искал правильный ответ и не смог найти ничего простого и удовлетворительного. Мне потребовалось некоторое время, но я смог кое-что записать.
Это решение на javascript, использующее рекурсию.
источник
На языке программирования Scala я бы сделал это так:
источник
Это простой рекурсивный алгоритм, который берет банкноту, затем рекурсивно берет меньшую банкноту, пока не достигнет суммы, затем берет другую банкноту того же достоинства и снова рекурсивно выполняет. См. Пример вывода ниже для иллюстрации.
Печатает следующее:
источник
Ах, я чувствую себя глупо прямо сейчас. Ниже есть слишком сложное решение, которое я буду оберегать , потому что это решение, в конце концов. Простое решение было бы таким:
Вот другое решение. Это решение основано на наблюдении, что каждая монета кратна другим, поэтому они могут быть представлены в их терминах.
Итак, для 37 монет, например:
источник
Эта моя запись в блоге решает эту проблему, как рюкзак, для фигур из комикса XKCD . Простое изменение слова
items
иexactcost
значения также даст все решения вашей проблемы.Если проблема заключалась в том, чтобы найти изменение, которое потребовало наименьшей стоимости, то наивный жадный алгоритм, который использовал бы как можно больше монет самой высокой стоимости, вполне мог бы потерпеть неудачу для некоторых комбинаций монет и целевой суммы. Например, если есть монеты достоинством 1, 3 и 4; а целевая сумма равна 6, тогда жадный алгоритм может предложить три монеты номиналом 4, 1 и 1, когда легко увидеть, что вы можете использовать две монеты номиналом 3 каждая.
источник
источник
Я нашел этот аккуратный фрагмент кода в книге Орейли «Python для анализа данных». Он использует ленивую реализацию и сравнение int, и я предполагаю, что его можно изменить для других номиналов с помощью десятичных знаков. Сообщите мне, как это работает для вас!
источник
Это улучшение ответа Зихана. Множество ненужных петель возникает, когда номинал составляет всего 1 цент.
Это интуитивно понятно и нерекурсивно.
источник
Простое решение Java:
источник
источник
Вот функция C #:
Используйте это так:
Он печатает:
источник
Ниже представлена программа на Python, которая позволяет найти все комбинации денег. Это решение динамического программирования с порядком (n) времени. Деньги 1,5,10,25
Переходим от денег 1-го ряда к деньгам 25 (4 ряда). Строка денег 1 содержит счет, если мы учитываем только деньги 1 при подсчете количества комбинаций. Строка money 5 создает каждый столбец, беря счет в строке money r для тех же конечных денег плюс предыдущие 5 счетчиков в собственной строке (текущая позиция минус 5). Строка денег 10 использует строку денег 5, которая содержит счет как для 1,5, так и для суммирования в предыдущих 10 счетах (текущая позиция минус 10). Деньги строки 25 используют деньги строки 10, которые содержат счетчики для денег строки 1,5,10 плюс предыдущие 25.
Например, числа [1] [12] = числа [0] [12] + числа [1] [7] (7 = 12-5) », что дает 3 = 1 + 2; числа [3] [12] = числа [2] [12] + числа [3] [9] (-13 = 12-25), что приводит к 4 = 0 + 4, так как -13 меньше 0.
источник
Решение Java
}
источник
Нижеприведенное java-решение, которое также распечатает различные комбинации. Легко понять. Идея
на сумму 5
Решение
Если оставшаяся сумма в каждом цикле меньше номинала, т.е. если оставшаяся сумма 1 меньше 2, то просто прервите цикл.
Полный код ниже
Пожалуйста, поправьте меня в случае ошибок
}
источник
Вот решение на основе Python, которое использует рекурсию, а также мемоизацию, что приводит к сложности O (mxn)
источник