Чему научитесь
- Выбирать структуру данных по условию, а не по привычке
- Соединять строки, списки, функции и словари в одном решении
- Замечать, где решение не пройдёт по времени, до отправки
- Проверять себя срезом из шести задач перед алгоритмами
Как устроено занятие
Сначала разбор с примерами и короткими проверками понимания — они нужны, чтобы поймать непонятое сразу, а не через три темы.
Дальше 15 задач лестницей: разминка, основа, со звёздочкой. Занятие засчитывается, когда решено 10 — остальные не пропадают и учитываются отдельно.
После практикума — контрольная: шесть задач по всему, что было в модулях о строках, списках и структурах данных. Подсказок там нет.
Сколько это займёт
Примерно час-полтора вместе с задачами. Сроков нет: можно закрыть вкладку и вернуться когда удобно — прогресс сохранится.
Три модуля, четыре структуры
За модули о строках, списках и структурах данных набрался инструмент, которого хватает на большинство задач начального уровня. Новой темы сегодня нет — есть выбор.
И выбирать теперь приходится не только приём, но и структуру данных. Одну и ту же задачу можно решить четырьмя способами, и разница будет не в красоте, а во времени работы.
| что нужно | чем решать |
|---|---|
| порядок важен, элементы повторяются | список |
| текст, слова, символы | строка и split |
| «сколько раз встретилось» | словарь |
| «есть или нет», уникальность | множество |
| одно вычисление применяется много раз | функция |
Признаки в условии:
- «сколько различных» — множество, одна строка;
- «самое частое» — словарь частот;
- «есть ли такое значение», причём в цикле — множество, иначе будет квадрат;
- «по возрастанию чего-то» — сортировка пар «признак и значение»;
- «сгруппировать по чему-то» — словарь, ключом признак.
Сегодня темы не подписаны, и рядом стоящие задачи почти никогда не про одно и то же.
Проверка: чем решать
Условие: «дан список из ста тысяч чисел и сто тысяч запросов; для каждого запроса ответьте, встречается ли значение в списке».
Что здесь нужно?
Двенадцать ошибок этих модулей
Собраны вместе, с признаком, по которому каждая узнаётся.
Строки
s[i + 1]на последнем шаге —string index out of range.- Результат метода потерян:
s.replace(...)без присваивания. Программа выводит введённое. - Срез с перепутанными границами — молча даёт кусок не той длины.
Списки
- Забытый
intпослеsplit— сравнение идёт по алфавиту,"10" < "9". b = aвместо копии — изменение через одно имя видно через другое.sortтам, где нужны исходные позиции.[[0] * m] * n— все строки таблицы оказываются одной.
Структуры данных
- Обращение к отсутствующему ключу —
KeyError. Лечитсяget. - Обход словаря там, где нужен порядок из списка, или наоборот забытый
sorted. - Печать множества напрямую — порядок непредсказуем.
Функции
printвместоreturn— снаружи получаетсяNone.- Рекурсия без базы или с двумя вызовами себя в шаге.
И про время
В этих модулях появился новый способ не пройти по времени: не медленный алгоритм, а неудачная структура.
Три случая, которые встречаются чаще всего:
- проверка
inпо списку внутри цикла — заменяется множеством; countилиindexвнутри цикла по тому же списку — заменяется словарём частот;- перебор всех пар там, где хватает одного прохода со словарём.
Во всех трёх случаях исправление занимает одну строку, а ускорение получается в тысячи раз. Поэтому при вердикте «превышено время» первым делом смотрите не на алгоритм, а на то, что стоит внутри цикла.
Прикидка прежняя: перемножьте количество повторений на стоимость того, что внутри. Проверка по множеству стоит единицы, по списку — его длины.
Практикум: пятнадцать задач
Лестница прежняя: пять разминочных, семь основных, три со звёздочкой. Зачёт при десяти решённых.
Подсказки в условиях остались, но они про выбор инструмента, а не про решение.
После практикума — контрольная: шесть задач без подсказок, по одной на крупную тему модулей 3–5. Порядок именно такой: практикум показывает, что подзабылось, и это можно закрыть до среза.
Верно, но не та структура
Задача: «даны список из чисел и запросов; для каждого запроса ответьте, встречается ли значение в списке».
Ученик написал:
n, q = map(int, input().split())
a = list(map(int, input().split()))
asks = list(map(int, input().split()))
for x in asks:
if x in a:
print("YES")
else:
print("NO")
Решение верное и короткое, но получает превышение времени. Объясните, сколько работы оно делает, почему замена одной строки всё меняет, и что именно изменится.