Все темы
105

Сдача наименьшим числом монет

Tier 1Закрыто

Где применяется

1. Задача

Многие задачи планирования и задачи на графах решаются так: на каждом шаге берёшь вариант, который сейчас выглядит лучше всех. Это и есть жадный подход. Ему всегда нужно обоснование: почему выбор, лучший на одном шаге, не испортит весь ответ.

Кассир в американском магазине должен тебе 40 центов сдачи. Монеты там бывают по 25, 10, 5 и 1 центу. Кассир не отсчитывает сорок монеток по одному центу. Он берёт 25, потом 10, потом 5, и готово: три монеты. Никто не учил его алгоритму. Он раз за разом берёт самую крупную монету, которая ещё не превышает остаток, пока сдача не набрана.

Тебе нужно то же самое в коде. Есть номиналы монет, которые лежат в автомате, и сумма к выдаче. Выдай её наименьшим числом монет. Банкомат решает эту задачу каждый раз, когда отсчитывает купюры. Торговый автомат решает её, когда выдаёт сдачу.

Правило «бери самую крупную» почти всегда даёт лучший ответ. В этом уроке ты узнаешь, на каких наборах монет оно работает и на каких ошибается.

Этот шаг из платной части

Бесплатные шаги в начале курса (их 33) открыты всем: урок, задача и тесты. Этот шаг открывается с полным доступом. Начни с бесплатного аккаунта и бесплатных шагов.

Завести бесплатный аккаунтПосмотреть, что входит
Жадно набрать 18 наименьшим числом монет
minCoinsGreedy([1, 5, 2, 10], 18)
coins
1
5
2
10
amount = 18
used
пусто

Нужно набрать 18 как можно меньшим числом монет. Жадное правило: всегда брать самую крупную монету, которая ещё помещается.

Гонка скорости
Перебор всех подмножеств и жадный выбор на одних и тех же 11 встречах: как уместить больше всего встреч без наложений

Столбики: когда заканчивается каждая встреча, в порядке их начала.

Одна операция: одна проверка встречи или одно сравнение при сортировке. За каждый кадр все дорожки делают одинаковое число операций, поэтому медленная отстаёт.

Перебор всех подмножеств O(2ⁿ·n)
операций: 0
Жадный выбор по времени окончания O(n log n)
операций: 0

 

А если чисел больше

Операции для n чисел и примерное время при 100 миллионах простых операций в секунду. Это оценка по тому же счёту, а не замер.

n = 10
Перебор всех подмножеств2,2 тыс. · меньше 1 мс
Жадный выбор по времени окончания33,3 · меньше 1 мс
n = 20
Перебор всех подмножеств2,2 млн · 22 мс
Жадный выбор по времени окончания80,5 · меньше 1 мс
n = 40
Перебор всех подмножеств2,3 трлн · 6,4 ч
Жадный выбор по времени окончания189 · меньше 1 мс

Как узнать

Жадный алгоритм (обменный аргумент) (Greedy (exchange argument))

Эти слова в условии значат этот паттерн

  • наименьшее число монет или частей на сумму
  • берём самую крупную, что ещё помещается
  • выдать сдачу номиналами
  • доказать оптимальность обменным аргументом

Похоже, но не то

O(n log n), если вход сначала нужно отсортировать. Проход после сортировки это один цикл, O(n).

На LeetCode

Задачи, где одно простое правило, например сначала самое большое или сначала самое маленькое, даёт лучший ответ. Прежде чем доверять правилу, проверь аргумент обмена и покажи, что замена его выбора на любой другой никогда не улучшает ответ. Сама Coin Change эту проверку не проходит, она будет в уроке 112.

Мы используем необходимые куки для работы сайта (вход и язык). Если ты согласишься, мы также загрузим Google Analytics, чтобы видеть, какие страницы читают, и Google reCAPTCHA для защиты форм обратной связи и сообщений об ошибке от спама. Политика конфиденциальности