Признак в условии
- «K самых частых / больших / близких»
- «k-й по величине»
- слияние нескольких отсортированных источников
- нужен минимум из постоянно меняющегося набора
Лестница решений - называть вслух все три
- Сортировка: O(n log n), пишется за минуту - нормальный первый ответ.
- Куча размера k: O(n log k) - держим только k лучших.
- Quickselect или bucket sort по частоте: O(n) в среднем.
Шаблон
В JS кучи нет в стандартной библиотеке, поэтому пишут свою на массиве: дети узла i лежат на 2i+1 и 2i+2, родитель - на (i−1)>>1. push кладёт в конец и всплывает, pop берёт корень, переносит последний элемент в корень и опускает.
Сложность
push и pop - O(log n), peek - O(1), построение из массива - O(n).
Частые ошибки
- при опускании сравнивают только с одним ребёнком
- pop оставляет дыру вместо перемещения последнего элемента
- берут max-кучу там, где для top-K нужна min-куча размера k (и наоборот)
Мнемоника
«Держи k лучших, выкидывай худшего»
Не путать с
- Жадность - куча - инструмент жадности, когда «лучший сейчас» меняется по ходу
- Монотонный стек - если нужен ближайший по позиции, а не k лучших, стек дешевле
- Бинарный поиск - k-й по величине можно искать и поиском по ответу, если элементы в диапазоне
Задачи на этот паттерн
- K самых частых
- k-й по величине
- слияние k отсортированных массивов