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

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

Полевой справочник

Два указателя (в одну сторону)

O(n)

Медленный указатель записи и быстрый указатель чтения оба движутся слева направо; быстрый сканирует вперёд, а медленный продвигается только когда значение стоит сохранить.

Сигналы

удалить дубликаты на месте, сохранив порядокпереместить/разбить элементы с сохранением порядкасжать массив, используя O(1) дополнительной памятисдвинуть нули или заданное значение в конец

Шаблон

function compact(arr) {
    let slow = 0;
    for (let fast = 0; fast < arr.length; fast++) {
        if (shouldKeep(arr[fast], arr[slow])) {
            arr[slow] = arr[fast];
            slow++;
        }
    }
    return slow; // new length
}

Похоже, но не то

  • Преобразование массива на месте: Работа на месте это более широкая цель (переписать один буфер, O(1) памяти); пара медленный/быстрый указатель это конкретный механизм для неё. Некоторым задачам на месте, например развороту фиксированного блока, пара указателей вообще не нужна.
  • Два указателя (с концов): Указатели с концов стартуют по краям отсортированных данных и сходятся навстречу друг другу. Указатели в одну сторону оба стартуют с индекса 0 и только движутся вперёд: один читает, другой пишет.

n до 1e5..1e6 -> O(n): быстрый указатель посещает каждый элемент один раз, медленный никогда его не обгоняет, поэтому хватает одного линейного прохода.

Изучить этот паттерн