Дан массив положительных чисел и положительное число target. Верните наименьшую длину подмассива, сумма которого не меньше target. Если такого подмассива нет, верните 0.
Алгоритмы на массивах · модуль 10 · окно переменного размера
Глава 10.2
Формулировки задач
и вопросы до решения
В этой главе разобрано, как звучит задача на окно переменного размера и что уточнить до кода. Сначала — части условия и слова, по которым узнаётся такое окно, восемь формулировок и случаи, когда оно не подходит. Затем — разговор с интервьюером о задаче КТП «минимальный отрезок с суммой не меньше S» и контракт функции. После него — вопросы ко второй задаче КТП и тестовые примеры, которые записывают до решения. В конце — тренажёр выбора техники.
- Категория
- Работа с условием
- Уровень
- Начальный
- Опирается на
- Глава 10.1; глава 9.2: части условия, признаки и контракт функции
- Зачем это знать
- Узнавать окно переменного размера по условию и уточнять задачу до кода
§1Из чего состоит условие
Условие задачи на окно состоит из тех же частей, что в главах 8.2 и 9.2: легенда, входные данные, результат, ограничения. В задаче на окно фиксированной длины во входных данных была длина окна k. В задаче этого модуля на её месте стоят две другие части. Первая — требование к отрезку, из которого получается условие допустимости. Вторая — направление поиска: нужен самый короткий отрезок или самый длинный.
s заказов, и верните его длину.s. Результат: наименьшая длина отрезка, сумма которого не меньше s.s»Легенда подсказывает ещё одно свойство входа. Число заказов не бывает отрицательным, поэтому каждый новый час сумму не уменьшает. От этого свойства зависит, подходит ли окно, поэтому его проверяют вопросом до решения, это разобрано в §4 и §5.
§2Восемь формулировок
Ниже восемь условий без подсказки, какую технику применить. Семь из них — пересказы задач LeetCode, ссылка в шапке карточки; условия сверены с сайтом. Восьмая — задача из статьи журнала Яндекс Образования, процитированной в главе 10.1. Кнопка под карточками подсвечивает слова, по которым узнаётся окно переменного размера.
Дана строка. Найдите длину самой длинной подстроки, в которой нет повторяющихся символов.
Дан массив из нулей и единиц и число k. Верните наибольшее число единиц подряд, которое можно получить, если заменить единицами не больше k нулей.
Из массива нулей и единиц нужно удалить один элемент. Верните длину самого длинного подмассива из одних единиц в получившемся массиве.
Деревья стоят в ряд, fruits[i] — вид фрукта на дереве i. Есть две корзины, в каждой — фрукты одного вида. Сборщик начинает с любого дерева, идёт вправо и берёт по одному фрукту с каждого дерева, пока фрукт подходит к корзинам. Верните наибольшее число собранных фруктов.
Дан массив чисел и число k. Массив называется хорошим, если каждое число встречается в нём не больше k раз. Верните длину самого длинного хорошего подмассива.
Дан массив положительных чисел и число 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] | 5 | 3 | 1 | Отрезок [5] подходит. Окно до него не сжалось: после ухода числа 3 сумма -2 + 5 равна 3, это меньше порога, и сжатие остановилось |
[3, 2, 5] | 5 | 1 | 1 | Все числа неотрицательные, ответы совпадают |
В главе 9.2 отрицательные числа окну не мешали: оно проходило все n − k + 1 окон подряд. Окно переменного размера проходит не все подотрезки. Оно пропускает те, которые не могут быть ответом, и определяет их по тому, что сумма при расширении не уменьшается. Поэтому вопрос о знаке чисел здесь обязателен.
§5Разговор с интервьюером о минимальном отрезке
Первая задача КТП занятия 10 — найти минимальный отрезок с суммой не меньше S. Слева — условие в том виде, в каком его произнёс интервьюер. Справа — вопросы. После каждого вопроса появляются ответ интервьюера и то, что он меняет в решении, а слева — новое уточнение. Порядок вопросов любой.
Первый вопрос решает, применима ли техника: при ответе «да, бывают отрицательные» решение было бы другим. Третий и пятый вопросы задают поведение функции на входах, для которых ответа нет. В КТП контроль занятия 10 требует, чтобы кандидат объяснял условие while. Это условие получается из четвёртого вопроса: знак >= в нём стоит потому, что сумма ровно s подходит.
§6Контракт функции
После разговора условие записывается как контракт: что функция принимает, что возвращает и что делает на неверном входе. В таблице для каждого ответа указано, какую часть решения он определяет.
| Ответ интервьюера | Куда попадает | Что это значит для решения |
|---|---|---|
| Числа неотрицательные, нули возможны | Выбор техники | Окно переменного размера; пример с нулями |
| Вернуть длину | Формат результата | Одно целое число, хранить наименьшую длину |
| Если отрезка нет — 0 | Начальное значение и тесты | Ответ начинается со значения «не найдено»; тесты на короткую сумму и пустой список |
| Сумма ровно s подходит | Условие допустимости | Знак >=; пример с суммой точно s |
s не меньше 1, иначе ValueError | Проверка входа и тесты | Проверка в первой строке; тесты на s = 0 и s < 0 |
| n до 10⁶, вход не менять | Выбор способа | Один проход, время O(n), память O(1); тест, что список после вызова тот же |
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 |
| Что вернуть: длину или саму подстроку? | Длину | Функция возвращает число, границы лучшего окна хранить не нужно |
| Подстрока — это символы подряд? | Да | Окно применимо. Если бы символы можно было пропускать, ответом было бы число разных символов строки |
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.
| nums | s | Ответ | Что проверяет |
|---|---|---|---|
[5, 8, 3, 12, 20, 6, 22, 9] | 30 | 2 | обычный случай: отрезок [12, 20] из главы 10.1 |
[2, 3, 1, 2, 4, 3] | 7 | 2 | сумма лучшего отрезка [4, 3] равна s точно |
[4, 40, 1] | 30 | 1 | достаточно одного элемента |
[1, 2, 3] | 6 | 3 | подходит только весь список |
[0, 0, 5, 0] | 5 | 1 | нули в списке |
[1, 1, 1, 1] | 5 | 0 | сумма всего списка меньше s |
[] | 3 | 0 | пустой список |
[1, 2] | 0 | ValueError | неверный порог |
Для второй задачи контроль КТП называет два класса входа прямо: «Проверяются дубликаты и пустая строка». Оба есть в таблице.
| 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: указатель чтения проходит список, указатель записи отмечает место для следующего нового значения.
- LeetCode. Условия задач 209, 3, 1004, 1493, 904, 2958, 713, 862, 300 — leetcode.com/problemset; условия и ограничения сверены по данным сайта 13.10.2026
- Журнал Яндекс Образования. Алгоритмические собеседования в Яндексе: как подготовиться и чего ожидать — education.yandex.ru/journal
- КТП ОП.04, занятие 10