Найти в Дзене
Каморка Программиста

Жадные алгоритмы, что это такое и как с этим работать

Оглавление

Народ, всем привет. В мире алгоритмов и программирования жадность может оказаться удивительно хорошей чертой. Я говорю о жадных алгоритмах, неком особом классе решений, которые принимают локально оптимальные решения на каждом шаге, надеясь, что это приведет к глобальному оптимуму. Если говорить проще, он на каждом своем шаге оценивает, что же ему выбрать, да так, чтобы это привело его к светлому будущему.

Но несмотря на свою простоту и "жадный" подход, такие алгоритмы часто оказываются эффективными и элегантными. Остаётся только вопрос, когда жадность действительно работает, а когда стоит быть с ней поосторожней. Давайте разберемся.

Суть жадных алгоритмов

Жадный алгоритм работает, как я уже сказал выше, по простой логике, он просто на каждом шаге выбирает то, что кажется наилучшим в текущий момент. Это может быть наименьшая стоимость, наибольшая выгода, минимальное расстояние, в зависимости от задачи. Главное — никакой "оглядки" на будущее или пересчета уже принятых решений. Такая стратегия резко контрастирует с методами, учитывающими множество вариантов развития событий, как в динамическом программировании или методах полного перебора.

-2

Этот подход делает жадные алгоритмы быстрыми и относительно простыми в реализации. Однако это же делает их уязвимыми, т.е. без гарантии глобальной оптимизации они могут давать неправильные или не самые лучшие результаты в сложных задачах.

При этом, жадные алгоритмы хорошо себя проявляют в задачах, обладающих свойствами оптимальности подструктур и жадного выбора. Это означает, что оптимальное решение всей задачи можно составить из оптимальных решений её подзадач (оптимальная подструктура). И локально наилучший выбор на каждом шаге ведёт к глобально оптимальному решению (жадность работает). А теперь давайте на примерах.

1. Задача о сдаче монетами

Возьмем классическую задачу, нужно выдать определённую сумму минимальным количеством монет. Если номиналы монет 1, 5, 10, 25, то на каждой итерации выбираем самую крупную монету, не превышающую оставшуюся сумму. В большинстве валют (например, с американскими или российскими номиналами) такой подход работает без ошибок. Но если номиналы задать особым образом (например, 1, 3, 4), жадный алгоритм может выбрать 4+1 вместо более выгодного 3+3.

-3
Хотите знать больше? Читайте нас в нашем Telegram – там еще больше интересного: новинки гаджетов, технологии, AI, фишки программистов, примеры дизайна и маркетинга.

2. Задача о покрытии отрезков

Допустим, нужно покрыть отрезок на прямой как можно меньшим числом других отрезков. Жадный подход выбирает на каждом шаге отрезок, начинающийся до или на текущей позиции и простирающийся как можно дальше. Этот метод работает оптимально, если предварительно отсортировать отрезки по началу.

3. Сортировка по активности

Дана куча мероприятий с временем начала и окончания. Требуется выбрать наибольшее количество непересекающихся мероприятий. Жадный алгоритм сортирует все активности по времени окончания и на каждом шаге выбирает первую подходящую активность. Этот метод гарантированно даёт оптимальное решение.

4. Остовное дерево минимального веса (алгоритмы Прима и Краскала)

Задачи из теории графов, где нужно соединить все вершины с минимальной суммой весов рёбер. Жадные алгоритмы тут незаменимы, и Прим, и Краскал на каждом шаге добавляют ребро с минимальным весом, не образующее цикл. Несмотря на жадность, они находят глобально оптимальное решение.

-4

Почему жадность работает не всегда

Не все задачи поддаются "жадному" решению. Например, в задаче о рюкзаке с целыми предметами (неразделимыми) жадный подход часто приводит к неоптимальному решению. Например, если есть предметы с высокой стоимостью на единицу веса, но в рюкзаке есть место для более выгодной комбинации из менее "эффективных" предметов, жадный алгоритм может выбрать неверно.

Также известна задача о наилучшем расписании с минимальной просрочкой, где каждый выбор влияет на дальнейшие. Здесь необходимо учитывать глобальные последствия, чего жадные алгоритмы делать не умеют.

Поэтому, если подвести итоги, что становится понятно, что жадные алгоритмы особенно полезны, когда задача допускает доказуемо корректное жадное решение. Когда важна скорость, а не абсолютная точность (например, при больших данных или в реальном времени) или необходимо быстрое приближенное решение. Иногда жадные алгоритмы применяются как часть более сложных стратегий, например, в эвристиках, жадных приближениях или стартовых решениях для других алгоритмов.

Жадный подход может давать не только правильный, но и эффективный результат в реальных приложениях. Один из ярких примеров, это алгоритм Хаффмана для сжатия данных. Он строит префиксное двоичное дерево, в котором часто встречающиеся символы имеют короткие коды. Алгоритм на каждом шаге жадно объединяет два самых редких символа. Как результат оптимальный способ кодирования с минимальной длиной.

-5

Если Вам нравятся наши статьи, и вы хотите отблагодарить автора (на развитие канала), нам будет очень приятно!