Сортировка

Обзор

Сортировка - один из самых частых приемов на алгоритмическом интервью. Иногда задача прямо просит упорядочить данные, но чаще сортировка появляется как подготовительный шаг: после нее становится проще сравнивать соседние элементы, искать пары, объединять интервалы или убирать дубликаты.

Важно понимать, что сортировка не бесплатна. Обычно она добавляет O(n * log n) по времени, зато часто убирает вложенный цикл и превращает решение из O(n²) в O(n * log n). Если количество возможных элементов небольшое, то можно использовать сортировку подсчетом за O(n).

Сортировка подсчетом работает, когда диапазон значений небольшой. Мы один раз проходим по массиву и считаем, сколько раз встретилось каждое значение. Потом идем по диапазону от минимума до максимума и записываем элементы в нужном количестве.

Для массива длины n и диапазона значений k сложность равна O(n + k). Если k намного меньше n * log n, такой подход быстрее обычной сортировки. Когда k ограничен константой, например от 1 до 100, его можно не учитывать, и сложность можно считать O(n).

Это удобно в задачах, таких как Height Checker: рост учеников лежит в диапазоне от 1 до 100, поэтому можно обойтись без O(n * log n).

Идея паттерна

Когда массив отсортирован, порядок элементов сам по себе дает полезную информацию. Мы заранее знаем, что все меньшие элементы находятся слева, а большие - справа. Это позволяет делать выводы без полного перебора.

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

Когда использовать

Сортировка часто помогает, когда в задаче есть такие признаки:

  1. Нужно сравнивать элементы между собой, но порядок исходного массива не важен.

  2. Нужно найти дубликаты, близкие значения или группы одинаковых элементов.

  3. Нужно объединить или проверить интервалы.

  4. Нужно найти пары или тройки с заданным свойством.

  5. Можно пожертвовать исходным порядком ради более простого решения.

Если порядок элементов важен по условию, сортировка может все сломать. В таких случаях нужно либо хранить исходные индексы вместе со значениями, либо выбирать другой способ решения.

Что важно на интервью

На практике редко просят написать QuickSort или MergeSort с нуля. Чаще интервьюер проверяет, можете ли вы заметить, что сортировка меняет форму задачи.

Нужно уметь объяснить три вещи:

  1. Почему после сортировки решение становится проще.

  2. Не теряем ли мы важную информацию об исходном порядке.

  3. Оправдана ли сложность O(n * log n).

Если сортировка используется только для удобства, интервьюер может спросить: "Можно ли решить за O(n)?" Часто ответом будет хеш-таблица, подсчет частот или специальный линейный алгоритм. Но сортировка все равно остается хорошей первой идеей, если она дает простое и корректное решение.

Пример

В задаче Height Checker нужно понять, сколько учеников стоят не на своих местах, если весь ряд должен быть отсортирован по росту.

Наивное решение - пытаться переставлять учеников вручную. Но проще сделать копию массива, отсортировать ее и сравнить с исходным массивом по индексам.

heights = [1, 1, 4, 2, 1, 3];
expected = [1, 1, 1, 2, 3, 4];

Индексы, где значения отличаются, показывают учеников, которые стоят не на своих местах.

Итоги

Сортировка полезна не только как самостоятельная операция, но и как способ сделать данные предсказуемыми. После сортировки соседние элементы, границы и направление движения указателей начинают давать информацию, которую до этого приходилось получать полным перебором.

Войдите чтобы отмечать прогресс