Модуль 9 · Скользящее окно · ОП.04

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

Глава 9.10

9.10

Практика, шпаргалка
и домашнее задание

В этой главе работа на паре по стартовому набору lesson_09: пять функций, 34 теста и замер. Затем вопросы для review по контролю КТП, шпаргалка, словарь модуля и домашнее задание: довести решения, найти три ошибки на границе окна и решить новую задачу с LeetCode. В конце — порядок сдачи и что будет на занятии 10.

Категория
Практика
Время на паре
Около 70 минут после 20 минут теории
Проверка
pytest, 34 теста
Результат
Папка portfolio/lesson_09 с решениями, замером и заметкой

§1Стартовый набор

В архиве всё, что нужно для работы на паре и дома. Функции в solution.py пустые: в каждой стоит raise NotImplementedError, поэтому до начала работы все 34 теста падают. Тесты границ из главы 9.6 в tests.py те же.

lesson_09/
solution.pyпять функций: суммы окон двумя способами, задачи 1 и 2, расширение
tests.py34 публичных теста pytest, среди них 12 тестов границ
bench.pyзамер сумм окон срезами и сдвигом, три опыта, глава 9.7
initial_attempt.txtвопросы к условию и примеры, записываются до кода
complexity_note.mdзаготовка заметки: состояние окна, инвариант, время, память, замер
task.mdусловия задач на пару
bugs_09.pyдомашнее задание: три функции с ошибкой на границе
tests_bugs_09.pyдомашнее задание: заготовки трёх тестов
homework_09.mdусловия домашнего задания
extra.pyдополнительные задачи: LeetCode 2379, 1876 и 1052
tests_extra.py15 тестов к дополнительным задачам
Функция в solution.pyЗадачаГлава
window_sums_slices, window_sums0 · сумма каждого окна срезами и сдвигом9.3
best_window1 · лучший отрезок длины k, задача КТП9.4
max_events2 · события во временном окне, задача КТП9.5
max_vowelsрасширение · LeetCode 14569.4, §8

§2Порядок работы на паре

Работа идёт в папке lesson_09 на своём компьютере, нужен Python с pytest. Если Python ещё не настроен, начните с песочниц в главах 9.3–9.6: там те же функции пишутся прямо на странице и проверяются похожими тестами. Сдаётся всё равно solution.py с зелёным pytest.

  1. Скопируйте папку lesson_09 в portfolio/lesson_09/ личного репозитория и выполните python -m pytest tests.py -v. Все 34 теста должны упасть — так проверяется, что pytest видит файлы.
  2. До кода откройте initial_attempt.txt и запишите три вопроса к условию задачи 1 и пять примеров с ответами, среди них k = 1, k = n и неверный k. Образец — глава 9.2.
  3. Напишите window_sums_slices, затем window_sums. Проверка: python -m pytest tests.py -k sums.
  4. Напишите best_window. Проверка: -k best, затем тесты границ: -k "bad_k or k_is". Если тест границы падает, сравните код со строками таблицы из главы 9.6, §1.
  5. Напишите max_events: -k events.
  6. Запустите замер: python bench.py > bench_results.txt. Он идёт около 35 секунд.
  7. Заполните complexity_note.md для четырёх обязательных функций.
  8. Если осталось время — max_vowels, -k vowels.
  9. Если и это готово — extra.py: перекраска блоков, подстроки из трёх разных букв, сердитый продавец. Проверка: python -m pytest tests_extra.py -v.
На полях: когда можно открыть главы

Код функций есть в главах модуля. На занятии 10 окно переменной длины строится на этом коде, поэтому сначала пишется своя версия по правилу из главы, не открывая код. Если тест падает, откройте пошаговый прогон нужной главы и сравните шаги со своим кодом.

§3Что сдаётся с пары

Работа на паре принята, когда

Суммы окон двумя способамиpython -m pytest tests.py -k sums — без падений.
Задачи КТП решены-k best, -k events и тесты границ -k "bad_k or k_is or bad_w or right_edge" — без падений.
Вопросы записаны до кодаВ initial_attempt.txt три вопроса и пять примеров.
Замер сохранёнbench_results.txt с выводом bench.py на своей машине.
Решение объясняетсяДля best_window вы можете назвать состояние окна, объяснить знак > и начальное значение best.

§4Вопросы для review

В КТП контроль занятия записан так: «Оценка O(n), тесты k=0/1/n и неверного k. Git review на корректность обновления окна». Ниже эти требования разложены на вопросы и на то, что должно прозвучать в ответе. Главы в правом столбце — где это разобрано.

Вопрос на reviewЧто должно прозвучать в ответеГде разобрано
Почему сдвиг окна — O(n), а срезы — O(n·k)?Срез заново читает k элементов для каждого из n − k + 1 окон; сдвиг исправляет сумму по двум изменившимся элементам за O(1). Свои числа из опыта 2 замера9.3, 9.7
Почему вложенный while в max_events не даёт O(n²)?l только растёт и не превышает r, за всю работу сдвигается не больше n раз9.5, §4
Какие тесты проверяют границы и что проверяет каждый?k = 1 — окно из одного элемента, сдвигов больше всего. k = n — одно окно, сдвигов нет. k = 0, k < 0, k > n и пустой список — ValueError9.6, §3 и §5
Как проверить, что окно обновляется верно?Первое окно — ровно k элементов и оно учтено; цикл с range(k, n); ушедший — nums[r − k]; сдвиг до сравнения; знак сравнения из условия9.6, §7
Почему на неверный k — исключение?Без проверки функция молча возвращает ответ для несуществующего окна; ValueError останавливает программу в строке вызова9.6, §2 и §4

§5Шпаргалка по модулю

Окно длины k: суммаtotal = sum(nums[:k]) best = total for r in range(k, len(nums)): total += nums[r] - nums[r - k] best = max(best, total)

r — пришедший, r − k — ушедший. Окно после сдвига — nums[r − k + 1:r + 1]. O(n), O(1).

Окно по времениl = 0 for r in range(len(times)): while times[r] - times[l] >= w: l += 1 best = max(best, r - l + 1)

Окно [s, s + w): при >= событие на правой границе не входит. l монотонный — O(n).

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

«длины k», «за k минут», «подряд», «подмассив», «подстрока» — окно фиксированной длины. «сумма не меньше S», «без повторов» без числа k — окно переменной длины, занятие 10.

Вопросы до кода

Что вернуть: значение, начало окна или само окно. Какое окно при равных ответах. Бывают ли отрицательные числа. Каким бывает k, что делать при k = 0 и k > n. Для окна по времени — открыта ли правая граница.

Состояние окна

Сумма, счётчик гласных, число белых блоков — исправляются по ушедшему и пришедшему за O(1). Максимум окна так не исправить — нужен дек, занятие 25.

Границы

k = 1 — окна совпадают с элементами. k = n — одно окно, цикл не выполняется. Неверный k и пустой список — ValueError до работы с окнами.

Сложность и замер

Срезы — O(n·k): при k = 100 время ×2 по n, при k = n/2 — ×4. Сдвиг — O(n) при любом k. Элемент среза дешевле шага цикла, поэтому при малых k разница меньше оценки.

Типичные ошибки

nums[r − k + 1] вместо nums[r − k]. Первое окно не в ответе. best = 0 при отрицательных. >= вместо > при «самом левом». range(k + 1, …). r − l вместо r − l + 1.

§6Словарь модуля

ТерминЧто означаетГде введён
Подотрезок, подмассивНесколько элементов, которые стоят подряд; в Python — срез a[l:r]9.1
ОкноПодотрезок, заданный полуинтервалом [l, r); длина r − l9.1
Скользящее окно фиксированного размераОкно длины k проходит список с шагом в одну позицию; окон n − k + 19.1, 9.3
Окно переменной длиныДлину окна задаёт условие, числа k в задаче нет; занятие 109.1, 9.2
Состояние окна, rolling stateОтвет для текущего окна, который исправляется при сдвиге за O(1)9.3
Сдвиг окнаПереход к соседнему окну: плюс пришедший элемент, минус ушедший9.3
Окно по времениОкно [s, s + w) на оси времени; число событий в нём меняется9.5
Монотонность указателяУказатель движется только в одну сторону; из неё следует O(n) и для цикла while внутри forмодуль 8, 9.5
Контракт функцииЧто функция принимает, что возвращает и что делает на неверном входе9.2, 9.6

§7Домашнее задание

Максим Николаевич не хочет задавать домашнее задание. Но очень хочет

Котёнок на клавиатуре ноутбука, подпись: «я чето нажала и всё исчезло»
ЗадачаЧто сделатьГде помогут
1 · Довести решенияsolution.py проходит все 34 теста. bench_results.txt — ваш замер. complexity_note.md заполнен по четырём функциям, в таблице замера — рост времени в трёх опытах.Главы 9.3–9.7
2 · Три ошибки на границеВ bugs_09.py функции count_strong_windows, min_window, count_in_window. Каждая верно отвечает на обычных входах и ошибается на граничном. Для каждой: вход, на котором ответ неверный; падающий тест в tests_bugs_09.py; исправление одной строки; повторный прогон. Вывод pytest — в bugs_run.txt.Глава 9.6, особенно §1 и чек-лист review
3 · Окна со средним не ниже порогаФункция count_good_windows(arr, k, threshold), LeetCode 1343: сколько окон длины k имеют среднее не меньше threshold; неверный k — ValueError. Пример: [2, 2, 2, 2, 5, 5, 5, 8], k = 3, threshold = 4 → 3. Время O(n), память O(1). Не меньше пяти своих тестов: k = 1, k = n, неверный k, окно со средним ровно на пороге.Главы 9.3 и 9.4: сдвиг и сравнение с порогом

Тест к bugs_09.py засчитывается, если до исправления он падает, а после — проходит. Тест, который проходит и на ошибочной версии, ошибку не ловит.

§8Порядок сдачи

Файлыportfolio/lesson_09/: solution.py, tests.py, bench_results.txt, complexity_note.md, initial_attempt.txt, bugs_09.py, tests_bugs_09.py, bugs_run.txt
Ветка и PRВетка hw-09, коммиты с содержательными сообщениями, Pull Request в собственную main. Review проводится по чек-листу из главы 9.6, §7
СрокДо начала занятия 10
ПроверяемЗелёный pytest по всем файлам; три теста к bugs_09.py, которые падают до исправления; пять тестов к count_good_windows; заметка без пустых пунктов
ИИКод и тесты пишете сами: на занятии 10 окно переменной длины строится на этом коде. Оформление .md и редактуру формулировок можно поручить модели. Я сам так делаю всегда, поэтому и вам запрещать не буду.

§9Что дальше

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

Занятие 10 — скользящее окно переменного размера. Длину окна там задаёт условие: «сумма не меньше S», «без повторяющихся символов». Правая граница расширяет окно, левая сжимает его, пока условие нарушено, — так же, как левая граница в задаче о событиях из главы 9.5. По КТП на занятии решаются задачи «минимальный отрезок с суммой не меньше S» и «подстрока без повторов», LeetCode 209 и 3.

Модуль 9 · Скользящее окно · ОП.04 · 3 курс Автор: Макаров Максим Николаевич