Что такое двоичная куча и очередь с приоритетом?
- Как найти k наибольших элементов?
- Как устроена PriorityQueue?
- Как куча хранится в массиве?
Двоичная куча — дерево, где родитель не больше потомков (min-heap): минимум всегда в корне, вставка и извлечение — O(log n).
- Хранится в массиве: потомки элемента i — 2i+1 и 2i+2, родитель — (i−1)//2
- Очередь с приоритетом почти всегда реализуют кучей
А ещё Применения: планировщик задач, алгоритм Дейкстры, k наибольших, слияние отсортированных потоков
Подробно
Куча — полное двоичное дерево с правилом: значение в каждом узле не больше значений его потомков (для min-кучи; в max-куче наоборот). Это слабее порядка в дереве поиска — между братьями порядка нет, — зато поддерживать такое правило дешевле.
Хранение в массиве. Полное дерево ложится в массив без пропусков: корень — в позиции 0, потомки элемента i — в 2i+1 и 2i+2, родитель — в (i−1)//2. Ссылки не нужны.
Операции:
- посмотреть минимум — O(1), это корень;
- вставка — кладём элемент в конец и «поднимаем» (sift up), пока он меньше родителя: O(log n);
- извлечение минимума — ставим последний элемент в корень и «опускаем» (sift down), меняя с меньшим потомком: O(log n);
- построение кучи из массива — O(n), а не O(n log n), если просеивать снизу вверх.
Очередь с приоритетом — структура «положить с приоритетом, достать самый приоритетный». Её почти всегда реализуют кучей: heapq в Python, PriorityQueue в Java.
Применения: планировщики задач, алгоритм Дейкстры и A*, поиск k наибольших элементов (куча размера k — O(n log k)), слияние k отсортированных списков, медиана потока (две кучи), пирамидальная сортировка.
Пример
import heapq
def top_k(nums, k):
heap = [] # min-куча из k наибольших
for x in nums:
heapq.heappush(heap, x)
if len(heap) > k:
heapq.heappop(heap) # выкидываем наименьший
return sorted(heap, reverse=True)
top_k([5, 1, 9, 3, 7, 2], 3) # [9, 7, 5]Что хотят услышать
- Свойство кучи и где находится минимум.
- Хранение в массиве и формулы индексов.
- Сложность операций, построение за O(n) — плюс.
- Применения, особенно очередь с приоритетом и задача о k наибольших.
Частые ошибки
- Путать кучу с деревом поиска — в куче нет полного порядка.
- Считать, что поиск произвольного элемента в куче O(log n) — он O(n).
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Куча хранит элементы полностью отсортированными в массиве, поэтому извлечение минимума — O(1), а вставка — O(n) из-за сдвига элементов
- ✗Извлечение минимума из кучи — O(n)
- ✗Куча хранится только как связное дерево с указателями
- ✓Родитель не больше потомков, минимум в корне, вставка и извлечение O(log n); очередь с приоритетом реализуют кучей
Что спросят дальше
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.