Самая короткая «сытая» серия перекусов

тема: Два указателя · уровень: продвинутый

Условие

После школы ты заходишь в магазин несколько раз подряд. В i-й заход ты покупаешь перекусы на сумму a[i].

Ты хочешь выбрать подряд идущие заходы так, чтобы общая сумма была не меньше S, и при этом таких заходов было как можно меньше.

Если ни один подряд идущий отрезок не набирает сумму хотя бы S, считай, что план не удался.

Формат ввода

Формат вывода Выведи одно целое число — минимальную длину подряд идущего отрезка с суммой >= S. Если такого отрезка нет, выведи 0.

Ограничения

Пример Ввод:

6 11
1 2 3 4 5 6

Вывод:

2

Пояснение: отрезок [5, 6] набирает 11, и короче уже нельзя.

Как решать — идея подхода

Приём: Два указателя (скользящее окно)

Ключевое наблюдение: все a[i] >= 1, значит сумма на отрезке монотонно меняется при движении границ. Если расширять окно вправо, сумма только растёт; если сдвигать левую границу вправо, сумма только уменьшается. Поэтому можно искать ответ одним проходом: как только сумма стала >= S, пытаемся сжать окно слева, не теряя условие — так и получаем минимальную длину для каждого правого конца.

Почему работает приём «два указателя»: каждая граница двигается только вперёд, назад не нужно, потому что «лишние» элементы слева уже точно не помогут сделать окно короче при том же правом конце.

План:

Сложность: O(n) по времени (каждый индекс уходит из окна максимум один раз) и O(1) по памяти.

Частая ошибка: использовать if cur_sum >= S вместо while — тогда окно не сожмётся до минимума, и ответ получится больше нужного.

Решить задачу с автопроверкой на Python →

Куда дальше