Все темы
83

Всегда брать наименьший, без пересортировки

Tier 1Закрыто

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

Очереди таймеровОчереди задач с приоритетом

1. Задача

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

Простое решение: держать список отсортированным. Тогда самая срочная задача всегда первая. Но каждую новую задачу приходится вставлять на её место, а для этого нужен проход по списку. Если задач приходят тысячи в секунду, эти вставки съедают всё время.

Полный порядок тебе не нужен. Нужно одно: быстро получать наименьшее значение, даже когда новые значения идут потоком. Куча (heap) даёт ровно это. В прошлых уроках ты писал её операции отдельными функциями. Теперь соберёшь их в класс, который можно использовать снова: очередь с приоритетом.

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

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

Завести бесплатный аккаунтПосмотреть, что входит
3 наименьших числа через max-кучу
kSmallest([5, 1, 8, 3, 9, 2], 3)
куча в виде дерева
пусто
та же куча в массиве, где она хранится
x = -k = 3heap.length = 0
снятые (слишком большие для k наименьших)
пусто

Храним 3 наименьших числа из [5, 1, 8, 3, 9, 2] в max-куче. В корне самое большое из оставленных, поэтому оно и уходит первым.

Гонка скорости
5 самых больших из одних и тех же 40 чисел: сортировка всего или куча на 5 элементов

Столбики: 40 чисел. Сортировка переставляет их все; куча их только читает, держит свои 5 чисел отдельно и подсвечивает то, которое сейчас рассматривает.

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

Сортировка всего массива O(n log n)
операций: 0
Куча минимумов на 5 элементов O(n log k)
операций: 0

 

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

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

n = 1 000
Сортировка всего массива19,9 тыс. · меньше 1 мс
Куча минимумов на 5 элементов1,2 тыс. · меньше 1 мс
n = 100 000
Сортировка всего массива3,3 млн · 33 мс
Куча минимумов на 5 элементов100,3 тыс. · 1 мс
n = 10 000 000
Сортировка всего массива465,1 млн · 4,7 с
Куча минимумов на 5 элементов10 млн · 100 мс

Как узнать

Бинарная куча / очередь с приоритетом (Binary heap / priority queue)

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

  • всегда нужен текущий минимум/максимум
  • k наименьших/наибольших элементов
  • слияние k отсортированных списков
  • текущая медиана, пока элементы прибывают
  • очередь с приоритетом / самое срочное следующим

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

n до 1e6 даёт O(log n) на вставку или снятие. Чтение вершины стоит O(1).

На LeetCode

Задачи, где снова и снова выбирают самый срочный элемент, пока прибывают новые, например планировщики задач или учёт свободных мест. Мин-куча отдаёт следующий элемент за O(log n) без повторной сортировки всего.

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