Бесплатная бета: 60 дней полного доступа, без карты.мест осталось: 84Зарегистрироваться бесплатно

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

Все паттерны

Бинарная куча / очередь с приоритетом

Binary heap / priority queue

O(log n) per op

Куча держит наверху наименьшее значение, а больше ничего не упорядочивает вообще. Вставка и снятие стоят по log n каждая.

Обновлено 17 окт. 2026 г.

Бинарная куча / очередь с приоритетом: как это работает?

Куча это дерево, лежащее в плоском массиве. Потомки индекса i стоят на 2i плюс один и два.

Единственное правило: родитель сильнее своих потомков. Между собой соседи не упорядочены никак.

Вставка пишет в конец, потом поднимает значение вверх. Оно меняется с родителем, пока сильнее него.

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

Оба действия идут по одному пути дерева. Высота равна log n, значит и стоимость тоже.

Смысл имеет только корень. Любая другая позиция произвольна.

Источники: Википедия: Двоичная куча, Документация Python (англ.): heapq

  1. [5]Кладём 5, 3 и 8. Первое значение становится корнем.
  2. [3, 5]Тройка кладётся и поднимается выше пятёрки.
  3. [3, 5, 8]Восьмёрка остаётся там, куда легла. Родителя она не бьёт.
  4. снятие возвращает 3Корень забирается. Наверх переезжает последний элемент, восьмёрка.
  5. [5, 8]Восьмёрка опускается под пятёрку. Новый корень это минимум остатка.
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 мс

Бинарная куча / очередь с приоритетом: шаблон кода

function kSmallest(nums, k) {
    const heap = []; // max-heap: keeps the k smallest seen so far
    const swap = (i, j) => ([heap[i], heap[j]] = [heap[j], heap[i]]);
    function push(v) {
        heap.push(v);
        let i = heap.length - 1;
        while (i > 0 && heap[(i - 1) >> 1] < heap[i]) { swap((i - 1) >> 1, i); i = (i - 1) >> 1; }
    }
    function pop() {
        const top = heap[0];
        heap[0] = heap.pop();
        let i = 0;
        while (2 * i + 1 < heap.length) {
            let c = 2 * i + 1;
            if (c + 1 < heap.length && heap[c + 1] > heap[c]) c++;
            if (heap[i] >= heap[c]) break;
            swap(i, c); i = c;
        }
        return top;
    }
    for (const x of nums) {
        push(x);
        if (heap.length > k) pop();
    }
    return heap.slice().sort((a, b) => a - b);
}

Бинарная куча / очередь с приоритетом: разбор примера

K ближайших точек к началу координат

Верните k точек, лежащих ближе всего к началу координат.

Список бывает слишком длинным для сортировки, а нужны только k точек.

Держите кучу размера k, на вершине которой худшая из сохранённых точек.

Кладите каждую точку и снимайте вершину, как только куча переросла k. Остаток и есть ответ.

function kClosest(points, k) {
    // a max-heap keyed by squared distance: the worst kept point sits on top
    const heap = new MaxHeap((p) => p[0] * p[0] + p[1] * p[1]);

    for (const point of points) {
        heap.push(point);

        if (heap.size() > k) {
            heap.pop(); // drops the farthest, never the closest
        }
    }

    return heap.toArray();
}

Бинарная куча / очередь с приоритетом: когда применять?

Паттерн «Бинарная куча / очередь с приоритетом» нужен, когда в условии есть слова «всегда нужен текущий минимум/максимум», «k наименьших/наибольших элементов» или «слияние k отсортированных списков». Решение на нём обычно укладывается в O(log n) per op.

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

Слова в условии для всех паттернов собраны в одной таблице: шпаргалка по паттернам алгоритмов.

Бинарная куча / очередь с приоритетом: с чем путают?

Паттерн «Бинарная куча / очередь с приоритетом» чаще всего путают с этими паттернами: Быстрая сортировка (merge / quick), Двоичное дерево поиска, Монотонная дек-очередь (максимум/минимум окна) и Алгоритм Дейкстры.

Бинарная куча / очередь с приоритетом: частые ошибки

  • Ждут отсортированный массив

    Упорядочен только корень. Чтение массива подряд даёт бессмыслицу.

  • Держат все элементы ради вопроса про k

    Куча размера k стоит O(n log k). Хранение всех тратит память впустую.

  • Строят кучу не в ту сторону

    Для k наибольших нужна min-куча, чтобы худший сохранённый был наверху. Это легко перепутать.

  • Пытаются удалить произвольный элемент

    У кучи нет дешёвого способа его найти. Пометьте его мёртвым и пропустите при всплытии.

Паттерн «Бинарная куча / очередь с приоритетом» решает такие задачи с собеседований: K-й по величине в потоке, K ближайших точек к началу, Слияние k отсортированных списков, K самых частых элементов, Планировщик задач, Медиана потока чисел и Кратчайший путь Дейкстры.

  • K-й по величине в потоке: Min-куча размера k, ответ лежит в корне.
  • K ближайших точек к началу: Ограниченная max-куча по квадрату расстояния.
  • Слияние k отсортированных списков: Куча держит головной узел каждого списка.
  • K самых частых элементов: Сначала счётчики, потом куча размера k.
  • Планировщик задач: Самая частая задача идёт первой в каждом раунде.
  • Медиана потока чисел: Две кучи, смотрящие друг на друга через середину.
  • Кратчайший путь Дейкстры: Куча решает, какую вершину закрывать следующей.

Бинарная куча / очередь с приоритетом: сложность по времени и памяти

У паттерна «Бинарная куча / очередь с приоритетом» целевая сложность O(log n) per op.

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

Где этот паттерн стоит в 150 шагах