Модуль 10 · Окно переменного размера · ОП.04

Алгоритмы на массивах · модуль 10 · окно переменного размера

Глава 10.2

10.2

Формулировки задач
и вопросы до решения

В этой главе разобрано, как звучит задача на окно переменного размера и что уточнить до кода. Сначала — части условия и слова, по которым узнаётся такое окно, восемь формулировок и случаи, когда оно не подходит. Затем — разговор с интервьюером о задаче КТП «минимальный отрезок с суммой не меньше S» и контракт функции. После него — вопросы ко второй задаче КТП и тестовые примеры, которые записывают до решения. В конце — тренажёр выбора техники.

Категория
Работа с условием
Уровень
Начальный
Опирается на
Глава 10.1; глава 9.2: части условия, признаки и контракт функции
Зачем это знать
Узнавать окно переменного размера по условию и уточнять задачу до кода

§1Из чего состоит условие

Условие задачи на окно состоит из тех же частей, что в главах 8.2 и 9.2: легенда, входные данные, результат, ограничения. В задаче на окно фиксированной длины во входных данных была длина окна k. В задаче этого модуля на её месте стоят две другие части. Первая — требование к отрезку, из которого получается условие допустимости. Вторая — направление поиска: нужен самый короткий отрезок или самый длинный.

Как звучитМагазин записывает число заказов каждый час. Найдите самый короткий промежуток из часов подряд, за который набралось не меньше s заказов, и верните его длину.
→
Что это значитВход: список чисел и число s. Результат: наименьшая длина отрезка, сумма которого не меньше s.
Легендамагазин, заказы, часы
→
Для решения не нужнаТа же задача про число шагов по дням и цель в 50 000 шагов решается тем же кодом.
Признаки«самый короткий», «подряд», «не меньше s»
→
Что подсказываютУчасток непрерывный, его длина не задана, на сумму участка стоит ограничение — окно переменного размера.

Легенда подсказывает ещё одно свойство входа. Число заказов не бывает отрицательным, поэтому каждый новый час сумму не уменьшает. От этого свойства зависит, подходит ли окно, поэтому его проверяют вопросом до решения, это разобрано в §4 и §5.

§2Восемь формулировок

Ниже восемь условий без подсказки, какую технику применить. Семь из них — пересказы задач LeetCode, ссылка в шапке карточки; условия сверены с сайтом. Восьмая — задача из статьи журнала Яндекс Образования, процитированной в главе 10.1. Кнопка под карточками подсвечивает слова, по которым узнаётся окно переменного размера.

Минимальный отрезокLeetCode 209

Дан массив положительных чисел и положительное число target. Верните наименьшую длину подмассива, сумма которого не меньше target. Если такого подмассива нет, верните 0.

самый короткий отрезок · состояние — сумма · глава 10.4
Без повторовLeetCode 3

Дана строка. Найдите длину самой длинной подстроки, в которой нет повторяющихся символов.

самый длинный отрезок · состояние — частотная карта · глава 10.5
Единицы с заменой нулейLeetCode 1004

Дан массив из нулей и единиц и число k. Верните наибольшее число единиц подряд, которое можно получить, если заменить единицами не больше k нулей.

самый длинный отрезок · состояние — счётчик нулей
Единицы после удаленияLeetCode 1493

Из массива нулей и единиц нужно удалить один элемент. Верните длину самого длинного подмассива из одних единиц в получившемся массиве.

самый длинный отрезок · нулей в окне не больше одного
Две корзиныLeetCode 904

Деревья стоят в ряд, fruits[i] — вид фрукта на дереве i. Есть две корзины, в каждой — фрукты одного вида. Сборщик начинает с любого дерева, идёт вправо и берёт по одному фрукту с каждого дерева, пока фрукт подходит к корзинам. Верните наибольшее число собранных фруктов.

самый длинный отрезок · разных значений не больше двух
Ограничение частотыLeetCode 2958

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

самый длинный отрезок · состояние — частотная карта
Произведение меньше kLeetCode 713

Дан массив положительных чисел и число k. Посчитайте, сколько непрерывных подмассивов имеют произведение строго меньше k.

подсчёт отрезков · состояние — произведение
Все числа различныЖурнал Яндекс Образования

Дан массив чисел. Найдите число подмассивов, в которых значения всех чисел различны.

подсчёт отрезков · состояние — частотная карта

В задачах 1004 и 1493 требование к отрезку названо не прямо. В условии говорится о замене и удалении элементов, но массив менять не нужно. «Заменить не больше k нулей» означает, что подходит любой отрезок, в котором нулей не больше k. «Удалить один элемент» означает, что в отрезке допускается не больше одного нуля. После такого пересказа обе задачи становятся поиском самого длинного отрезка со счётчиком нулей.

§3Признаки в условии

Подсвеченные слова повторяются от задачи к задаче. Технику выбирают по сочетанию трёх признаков: участок идёт подряд, его длина в условии не задана, и на содержимое участка стоит ограничение.

Слова в условииЧто они сообщаютВывод
«подряд», «непрерывный», «подмассив», «подстрока»Участок — элементы, стоящие рядом, без пропусковокно: элементы выбираются только подряд
«не меньше S», «не больше k», «меньше k», «без повторов», «все различны»Ограничение на содержимое участкаусловие допустимости; длина окна зависит от данных
«самый короткий», «наименьшая длина»Из допустимых участков нужен самый короткийсжимать окно, пока оно допустимо
«самый длинный», «наибольшее число подряд»Из допустимых участков нужен самый длинныйсжимать окно, пока оно недопустимо
«сколько подмассивов» вместе с ограничениемНужно число допустимых участковдля каждого положения правой границы считать допустимые окна
«можно заменить не больше k», «удалить один элемент»Ограничение названо через действиепересказать: «плохих» элементов в окне не больше k
«положительные», «неотрицательные», «из нулей и единиц»Расширение меняет сумму или счётчик только в одну сторонуокно применимо, это разобрано в §4

§4Когда окно переменного размера не подходит

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

УсловиеНайдите самый короткий подмассив с суммой не меньше S. Числа могут быть отрицательными.

РешениеОтрицательное число при расширении уменьшает сумму, а при сжатии увеличивает. По сумме уже нельзя определить, какую границу сдвигать. Задача решается префиксными суммами и деком, это LeetCode 862 уровня Hard. До занятий 11 и 25 остаётся перебор за O(n²).

УсловиеНайдите самую длинную возрастающую подпоследовательность: элементы можно пропускать.

РешениеУчасток не непрерывный, окно таких наборов не рассматривает. Это LeetCode 300, он решается динамическим программированием. Слова «подпоследовательность» и «подстрока» в условии различают до решения.

УсловиеНайдите подмассив длины k с наибольшей суммой.

РешениеДлина задана числом, условия допустимости в задаче нет. Это окно фиксированной длины из модуля 9: обе границы сдвигаются вместе, цикл while не нужен.

Первый случай проверен запуском. Окно, которое расширяется при сумме меньше порога и сжимается при сумме не меньше порога, запущено на списке [3, -2, 5] с порогом 5. Рядом — ответ перебора всех подотрезков.

СписокSОтвет окнаОтвет перебораПочему ответы разные
[3, -2, 5]531Отрезок [5] подходит. Окно до него не сжалось: после ухода числа 3 сумма -2 + 5 равна 3, это меньше порога, и сжатие остановилось
[3, 2, 5]511Все числа неотрицательные, ответы совпадают
На полях: отличие от окна фиксированной длины

В главе 9.2 отрицательные числа окну не мешали: оно проходило все n − k + 1 окон подряд. Окно переменного размера проходит не все подотрезки. Оно пропускает те, которые не могут быть ответом, и определяет их по тому, что сумма при расширении не уменьшается. Поэтому вопрос о знаке чисел здесь обязателен.

§5Разговор с интервьюером о минимальном отрезке

Первая задача КТП занятия 10 — найти минимальный отрезок с суммой не меньше S. Слева — условие в том виде, в каком его произнёс интервьюер. Справа — вопросы. После каждого вопроса появляются ответ интервьюера и то, что он меняет в решении, а слева — новое уточнение. Порядок вопросов любой.

Минимальный отрезок с суммой не меньше S
условие от интервьюера

«Дан список чисел — заказы магазина по часам — и число s. Найдите самый короткий промежуток из часов подряд, за который набралось не меньше s заказов».

уточнено

    Первый вопрос решает, применима ли техника: при ответе «да, бывают отрицательные» решение было бы другим. Третий и пятый вопросы задают поведение функции на входах, для которых ответа нет. В КТП контроль занятия 10 требует, чтобы кандидат объяснял условие while. Это условие получается из четвёртого вопроса: знак >= в нём стоит потому, что сумма ровно s подходит.

    §6Контракт функции

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

    Ответ интервьюераКуда попадаетЧто это значит для решения
    Числа неотрицательные, нули возможныВыбор техникиОкно переменного размера; пример с нулями
    Вернуть длинуФормат результатаОдно целое число, хранить наименьшую длину
    Если отрезка нет — 0Начальное значение и тестыОтвет начинается со значения «не найдено»; тесты на короткую сумму и пустой список
    Сумма ровно s подходитУсловие допустимостиЗнак >=; пример с суммой точно s
    s не меньше 1, иначе ValueErrorПроверка входа и тестыПроверка в первой строке; тесты на s = 0 и s < 0
    n до 10⁶, вход не менятьВыбор способаОдин проход, время O(n), память O(1); тест, что список после вызова тот же
    solution.pyконтракт после уточнений
    def shortest_window(nums, s):
        """Окно переменного размера. Задача 1 занятия 10.
    
        nums — список целых неотрицательных чисел, может быть пустым.
        s — порог суммы, s >= 1; иначе ValueError.
        Возвращает длину самого короткого отрезка подряд с суммой не меньше s.
        Если такого отрезка нет, возвращает 0. Список не меняется.
        Время O(n), память O(1).
        """

    Контракт совпадает с условием LeetCode 209 во всём, кроме двух мест. На сайте числа строго положительные, а пустого списка и неверного порога во входе не бывает. Функция из этой главы принимает более широкий вход и на входах сайта возвращает те же ответы. Для отправки на сайт её тело переносят в функцию minSubArrayLen(target, nums): там порог стоит первым параметром.

    §7Вопросы к задаче о подстроке

    Вторая задача КТП — найти самую длинную подстроку без повторов. Чисел и суммы в ней нет, поэтому вопросы другие: они про то, что считается символом и что считается повтором. Разговор строится так же — каждый вопрос заканчивается изменением в решении. Сама задача разобрана в главе 10.5.

    ВопросТипичный ответЧто меняет
    Какие символы бывают в строке?Любые: буквы, цифры, знаки, пробелыДля счёта символов нужен словарь; массив на 26 букв не подходит. Пробел считается обычным символом
    Заглавная и строчная буква — один символ или разные?РазныеСтроку не приводят к одному регистру; нужен пример 'aA'
    Строка может быть пустой?ДаДля пустой строки ответ 0; начальное значение ответа — 0
    Что вернуть: длину или саму подстроку?ДлинуФункция возвращает число, границы лучшего окна хранить не нужно
    Подстрока — это символы подряд?ДаОкно применимо. Если бы символы можно было пропускать, ответом было бы число разных символов строки
    solution.pyконтракт второй задачи
    def longest_unique(text):
        """Окно переменного размера с частотной картой. Задача 2 занятия 10.
    
        text — строка из любых символов, может быть пустой.
        Возвращает длину самой длинной подстроки, в которой все символы разные.
        Регистр различается: 'a' и 'A' — разные символы. Для пустой строки — 0.
        Время O(n), память O(m), m — число разных символов строки.
        """
    На полях: подстрока и подпоследовательность

    Подстрока — символы строки, которые стоят подряд: в строке 'pwwkew' это, например, 'wke'. Подпоследовательность — символы в том же порядке, но с пропусками: 'pwke'. В примерах к LeetCode 3 это различие оговорено отдельно: для 'pwwkew' ответ 3, а 'pwke' длины 4 ответом не является, потому что это подпоследовательность.

    §8Тестовые примеры до кода

    Как и в главе 9.2, после вопросов записывают входы с ответами. Каждый пример проверяет свой класс входа: обычный случай, ответы на уточнения и случаи без ответа. Ответы получены запуском эталонных решений на Python 3.12.

    numssОтветЧто проверяет
    [5, 8, 3, 12, 20, 6, 22, 9]302обычный случай: отрезок [12, 20] из главы 10.1
    [2, 3, 1, 2, 4, 3]72сумма лучшего отрезка [4, 3] равна s точно
    [4, 40, 1]301достаточно одного элемента
    [1, 2, 3]63подходит только весь список
    [0, 0, 5, 0]51нули в списке
    [1, 1, 1, 1]50сумма всего списка меньше s
    []30пустой список
    [1, 2]0ValueErrorневерный порог

    Для второй задачи контроль КТП называет два класса входа прямо: «Проверяются дубликаты и пустая строка». Оба есть в таблице.

    textОтветЧто проверяет
    'abcabcbb'3обычный случай: 'abc'
    'bbbbb'1все символы одинаковые
    'pwwkew'3повтор стоит рядом: 'ww'; ответ 'wke'
    'abba'2повтор символа, который уже вышел из окна
    'aA'2регистр различается
    'a b a'3пробел считается символом и тоже повторяется
    'z'1один символ
    ''0пустая строка

    Пример 'abba' проверяет случай, когда повторяется символ, который уже вышел из окна: вторая буква a повтором для окна 'b' не является. Этот пример понадобится в главе 10.5. Все примеры из обеих таблиц войдут в тесты стартового набора.

    §9Тренажёр: выберите технику

    Ниже шесть условий. Для каждого выберите способ, который подходит при указанных ограничениях и работает быстрее остальных вариантов. После ответа открывается разбор верного и выбранного вариантов.

    Условие 1Известны расходы по дням, числа неотрицательные. Найдите самый длинный промежуток из дней подряд, за который потрачено не больше бюджета B.

    • Ответ будет верным, но для каждой длины нужен свой проход, всего O(n²). Длина в условии не задана.

    • Верно. Условие допустимости — «сумма не больше B». Окно расширяется вправо и сжимается слева, пока сумма больше B. Один проход, O(n).

    • Сортировка теряет порядок дней, а промежуток должен идти подряд.

    Условие 2Датчик присылает показание раз в минуту. Найдите наибольшую сумму показаний за любые 10 минут подряд.

    • Верно. Длина участка задана числом, условия допустимости нет. Это окно фиксированной длины из модуля 9.

    • Ограничения на содержимое участка в задаче нет, поэтому у окна нет условия допустимости. Длина окна известна заранее — 10.

    • Указатели навстречу сравнивают элементы с разных концов. Здесь нужны участки из 10 показаний подряд.

    Условие 3Дана строка из строчных букв. Найдите самую длинную подстроку, в которой не больше двух разных букв.

    • Число 2 ограничивает количество разных букв. Длина подстроки не ограничена: в строке 'aabbb' ответ — вся строка длины 5.

    • Счёт по всей строке не учитывает, стоят ли буквы подряд. Нужен счёт внутри окна, который меняется при сдвиге границ.

    • Верно. Условие допустимости — «разных букв в окне не больше двух». Число разных букв — это число ключей частотной карты. Та же схема, что в LeetCode 904.

    Условие 4Найдите самый короткий отрезок с суммой не меньше 100. В списке до 1 000 чисел, они могут быть отрицательными.

    • С отрицательными числами окно даёт неверный ответ, пример есть в §4: на списке [3, -2, 5] с порогом 5 оно отвечает 3 вместо 1.

    • Верно. Из способов, пройденных к этому занятию, верный ответ даёт только перебор. При n до 1 000 это около 500 000 подотрезков, по времени подходит.

    • Сортировка теряет порядок, а отрезок должен идти подряд.

    Условие 5Дан массив из нулей и единиц. Найдите самый длинный отрезок из единиц, если разрешено заменить единицами не больше трёх нулей.

    • Верно. После пересказа это «самый длинный отрезок, в котором нулей не больше трёх». Массив менять не нужно. Это LeetCode 1004.

    • Троек нулей около z³/6, где z — число нулей, и после каждой замены нужен проход по массиву. Замену выполнять не требуется.

    • Замена нулей может соединить несколько серий. В массиве [1, 0, 1, 0, 1, 0, 1] самая длинная серия имеет длину 1, а ответ равен 7: три замены соединяют четыре серии.

    Условие 6Список отсортирован по возрастанию. Удалите из него повторы на месте и верните новую длину.

    • Окно ищет участок списка и список не меняет. Здесь нужно переписать элементы на месте.

    • Указатели навстречу сравнивают элементы с разных концов. Повторы в отсортированном списке стоят рядом.

    • Верно. Это задача из главы 8.7: указатель чтения проходит список, указатель записи отмечает место для следующего нового значения.

    Источники главы
    1. LeetCode. Условия задач 209, 3, 1004, 1493, 904, 2958, 713, 862, 300 — leetcode.com/problemset; условия и ограничения сверены по данным сайта 13.10.2026
    2. Журнал Яндекс Образования. Алгоритмические собеседования в Яндексе: как подготовиться и чего ожидать — education.yandex.ru/journal
    3. КТП ОП.04, занятие 10
    Модуль 10 · Окно переменного размера · ОП.04 · 3 курс Автор: Макаров Максим Николаевич