---
title: Greedy Algorithms
localeTitle: Жадные алгоритмы
---
## Что такое жадный алгоритм

Вы, должно быть, слышали о многих алгоритмических методах проектирования, просеивая некоторые из статей здесь. Некоторые из них :

*   Грубая сила
*   Разделить и покорить
*   Жадное программирование
*   Динамическое программирование назвать несколько. В этой статье вы узнаете, что такое жадный алгоритм и как вы можете использовать эту технику для решения многих проблем программирования, которые в противном случае не кажутся тривиальными.

Представьте, что вы собираетесь отправиться в поход, и ваша цель - достичь максимально возможного пика. У вас уже есть карта, прежде чем вы начнете, но есть тысячи возможных путей, отображаемых на карте. Вы слишком ленивы и просто не имеете времени оценить каждую из них. Вверните карту! Вы начали поход с простой стратегией - быть жадным и близоруким. Просто пройдите по дорожкам, которые больше склоняются вверх. Это похоже на хорошую стратегию для пеших прогулок. Но всегда ли это лучше?

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

## Формальное определение

Предположим, что у вас есть целевая функция, которая должна быть оптимизирована (максимизирована или минимизирована) в данной точке. Алгоритм Greedy делает жадные варианты на каждом шаге, чтобы оптимизировать целевую функцию. Алгоритм Жадности имеет только один выстрел для вычисления оптимального решения, чтобы он никогда не возвращался и не менял решение.

### Жадные алгоритмы имеют некоторые преимущества и недостатки:

*   Легко придумать жадный алгоритм (или даже несколько жадных алгоритмов) для проблемы. Анализ времени выполнения жадных алгоритмов будет намного проще, чем для других методов (например, Divide and conquer). Для техники «Разделить и властвовать» неясно, является ли техника быстрой или медленной. Это связано с тем, что на каждом уровне рекурсии размер уменьшается и увеличивается количество подзадач.
    
*   Трудная часть заключается в том, что для жадных алгоритмов вам приходится много работать, чтобы понять проблемы правильности. Даже при правильном алгоритме трудно доказать, почему оно правильно. Доказательство правильности жадного алгоритма - это скорее искусство, чем наука. Это связано с большим количеством творчества. Обычно придумывание алгоритма может показаться тривиальным, но доказывая, что оно на самом деле правильно, представляет собой совершенно другую проблему.
    

## Проблема с интервальным расписанием

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

*   В течение одного дня в университете вам предоставляется набор N графиков лекций. График для конкретной лекции имеет вид ( _время,_ время), где _время представляет собой время начала этой лекции, и аналогично время f_ представляет время окончания. Учитывая список N расписаний лекций, нам нужно выбрать максимальный набор лекций, которые будут проводиться в течение дня, чтобы **ни одна из лекций не совпадала одна с другой, т.е. если лекция Li и Lj включены в наш выбор, тогда время начала j > = время окончания i или наоборот** .
    
*   Ваш друг работает в качестве советника лагеря, и он отвечает за организацию мероприятий для набора отдыхающих. Один из его планов состоит в следующем упражнении по мини-триатлону: каждый участник должен поплавать 20 кругов пула, затем проехать 10 миль, затем пробежать 3 мили.
    
*   План состоит в том, чтобы отправить участников в шахматном порядке по следующему правилу: участники должны использовать пул по одному за раз. Другими словами, первый участник соревнований плавает по 20 кругов, выходит и начинает кататься на велосипеде.
    
*   Как только этот первый человек выходит из бассейна, второй участник начинает плавать 20 кругов; как только он или она выходит и начинает кататься на велосипеде, третий участник начинает плавать и так далее.
    
*   Каждый участник имеет запланированное время плавания, прогнозируемое время езды на велосипеде и прогнозируемое время работы. Ваш друг хочет принять решение о расписании для триатлона: порядок, в котором можно начинать старты конкурсантов.
    
*   Предположим, что время завершения расписания - это самое раннее время, когда все участники будут закончены со всеми тремя ногами триатлона, предполагая, что прогнозы времени точны. Каков наилучший порядок отправки людей, если вы хотите, чтобы весь конкурс закончился как можно скорее? Точнее, дать эффективный алгоритм, который создает график, время завершения которого как можно меньше
    

### Проблема планирования лекций

Давайте рассмотрим различные подходы к решению этой проблемы.

1.  **Самое раннее время начала Сначала** выберите интервал, который имеет самое раннее время начала. Взгляните на следующий пример, который нарушает это решение. Это решение не получилось, потому что может быть интервал, который начинается очень рано, но очень длинный. Это означает, что следующая стратегия, которую мы могли бы попробовать, будет заключаться в том, чтобы сначала посмотреть на меньшие интервалы. ![Самое раннее время начала](https://algorithmsandme.files.wordpress.com/2015/03/f268b-jobs.png?w=840)
    
2.  **Наименьший интервал Первый,** т. Е. Вы в конечном итоге выбираете лекции в порядке их общего интервала, который является ничем иным, как их `finish time - start time` . Опять же, это решение неверно. Посмотрите на следующий случай. ![Кратчайший интервал](https://i.stack.imgur.com/4bz2N.png)
    

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

3.  **Наименее конфликтный интервал Сначала** вы должны смотреть на интервалы, которые вызывают наименьшее количество конфликтов. Еще раз у нас есть пример, когда этот подход не находит оптимального решения. ![Наименее конфликтный интервал](https://i.stack.imgur.com/5LZ9V.png)

Диаграмма показывает нам, что наименьший интервал согласования - это один посередине с двумя конфликтами. После этого мы можем выбрать только два интервала в самом конце с конфликтами 3 каждый. Но оптимальным решением является выбор 4 интервалов на самом верхнем уровне.

4.  **Самое раннее время окончания** . Это тот подход, который всегда дает нам наиболее оптимальное решение этой проблемы. Мы получили много идей из предыдущих подходов и, наконец, пришли к такому подходу. Мы сортируем интервалы в соответствии с возрастающим порядком их времени окончания, а затем начинаем выбирать интервалы с самого начала. Посмотрите на следующий псевдо-код для большей ясности.
```
function interval_scheduling_problem(requests) 
    schedule \gets \{\} 
    while requests is not yet empty 
        choose a request i_r \in requests that has the lowest finishing time 
        schedule \gets schedule \cup \{i_r\} 
        delete all requests in requests that are not compatible with i_r 
    end 
    return schedule 
 end 
```

## Когда мы используем Жадные алгоритмы

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

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

1.  Кратчайший путь.
2.  Минимальная проблема связующего дерева на графике.
3.  Проблема кодирования Хаффмана.
4.  Проблема K-центров

#### Дополнительная информация:

 [![Жадные проблемы](http://img.youtube.com/vi/HzeK7g8cD0Y/0.jpg)](https://www.youtube.com/watch?v=HzeK7g8cD0Y) 

 [![Жадные проблемы](http://img.youtube.com/vi/poWB2UCuozA/0.jpg)](https://www.youtube.com/watch?v=poWB2UCuozA)