Признак в условии
- массив пар [начало, конец]
- «слить пересекающиеся», «можно ли посетить все», «сколько нужно комнат»
- расписания, бронирования, отрезки времени
Идея
Почти всё решается сортировкой по началу и одним проходом. Задачи про «сколько одновременно» - сканирующей прямой: отдельно отсортированные начала и концы, идём по времени и считаем открытые интервалы.
Шаблон
const sorted = [...intervals].sort((a, b) => a[0] - b[0]);
const out = [sorted[0].slice()];
for (let i = 1; i < sorted.length; i++) {
const last = out[out.length - 1];
if (sorted[i][0] <= last[1]) last[1] = Math.max(last[1], sorted[i][1]);
else out.push(sorted[i].slice());
}
Сложность
Время O(n log n) на сортировку, память O(n).
Частые ошибки
last[1] = cur[1]вместоMath.max: вложенный интервал обрезает предыдущий- мутация входных интервалов
- путаница строгого и нестрогого сравнения на касании границ - надо уточнить у интервьюера
Мнемоника
«Отсортируй по началу, тяни конец максимумом»
Не путать с
- Жадность - интервалы почти всегда решаются жадно после сортировки: сортировка по началу - слияние, по концу - максимум непересекающихся
- Скользящее окно - окно - про непрерывный участок одного массива; интервалы - про множество отрезков с началом и концом
Задачи на этот паттерн
- слияние интервалов
- можно ли посетить все встречи
- вставка интервала
- сколько нужно переговорок
- минимум удалений интервалов
- пересечение двух списков