Задача №1 LeetCode — и образец мышления через словарь.
⏱️ ~1 ч 15 мин·Средний·📚 5 уроков
Бытовая аналогия
Представьте, что вы стоите у кассы и хотите расплатиться ровно двумя купюрами так, чтобы получилась нужная сумма — скажем, 9 рублей. Вы достаёте первую купюру (2 рубля) и думаете: «мне не хватает 7». Дальше вы не перебираете заново весь кошелёк — вы просто помните, что ищете семёрку. Как только семёрка попадётся, задача решена.
Именно так работает «умное» решение задачи Two Sum: вместо того чтобы каждый раз перебирать все купюры заново, мы запоминаем уже виденные числа и для каждого нового сразу проверяем — а не встречали ли мы уже его «недостающую половинку».
Условие
Дан списокИзменяемая упорядоченная коллекция элементов: [1, 2, 3]. По-английски list. чисел nums и число target. Нужно вернуть индексыНомер позиции элемента в последовательности. В Python нумерация с нуля: первый элемент — индекс 0. двух элементов, которые в сумме дают target. Гарантируется ровно одно решение.
Пример: nums = [2, 7, 11, 15], target = 9 → ответ [0, 1], потому что nums[0] + nums[1] = 2 + 7 = 9.
Наивное решение O(n²)
Перебрать все пары двумя циклами. Работает, но медленно — это как доставать из кошелька первую купюру и каждый раз заново перебирать все остальные:
▶ two-sum-slow.py
Быстрое решение O(n) через словарь
Ключевая идея: для каждого числа x нам нужно target - x (дополнение). Будем запоминать виденные числа в словарьКоллекция пар «ключ → значение»: {"a": 1}. Быстрый доступ по ключу. По-английски dict.число → индекс и для каждого нового проверять, не встречали ли мы уже его дополнение.
▶ two-sum-fast.py
Разбираем быстрый код по строкам
Этот код — образец, который стоит понять до последней буквы. Разберём каждую строкуТекстовое значение в кавычках: "привет". Неизменяема. По-английски string (str).циклаКонструкция, повторяющая блок кода: for перебирает элементы, while — пока условие истинно.:
seen = {} — создаём пустой словарь. Здесь мы будем хранить пары «число → его индекс». Это наша «память» о том, что уже видели.
for i, x in enumerate(nums) — идём по списку, получая сразу и индексi, и значениеx.
need = target - x — вычисляем «недостающую половинку». Если сейчас x = 2, а target = 9, то need = 7.
if need in seen — проверяем, не встречали ли мы уже это число раньше. Проверка «есть ли ключ в словаре» работает мгновенно — O(1).
return [seen[need], i] — если встречали: возвращаем индекс той «половинки» (он лежит в словаре) и текущий индекс i.
seen[x] = i — если не встречали: запоминаем текущее число и его индекс на будущее.
💡Совет
ФункцияИменованный блок кода, который можно вызывать многократно. Может принимать аргументы и возвращать результат.enumerate(nums) на каждом шаге даёт пару «индекс, значение». Это удобнее, чем range(len(nums)) с обращением nums[i]. Запомните этот приём — он встречается постоянно.
💡Совет
🔮 Предскажите вывод
Прежде чем запускать следующую ячейку — подумайте: какие индексы вернёт two_sum для списка [1, 5, 3, 8] и target 11? Какие два числа дают в сумме 11 и под какими они индексами?
▶ predict-two-sum.py
Ответ — [2, 3]. Числа 3 (индекс 2) и 8 (индекс 3) дают в сумме 11. Когда цикл доходит до x = 8, он ищет need = 11 - 8 = 3, а тройку мы уже видели и записали в seen с индексом 2. Поэтому ответ — [2, 3].
⚠️ Частые ошибки новичков
Очень распространённая ошибка — записывать число в словарь до проверки. Тогда для пары одинаковых чисел можно случайно «найти» само число дважды. Ниже код намеренно сломан: число добавляется в seen раньше проверки. Запустите, увидите неверный результат, и переставьте строки так, чтобы seen[x] = i шло послеif.
▶ broken-two-sum.py
Заданиесредняярешение.py
Реализуйте two_sum(nums, target) через словарь за O(n). Верните индексы двух чисел, дающих в сумме target.
Заданиелёгкаярешение.py
Дополнительное упражнение. Напишите has_pair_with_sum(nums, target), которая возвращает True, если в списке есть хотя бы одна пара чисел с суммой target, и False иначе. Используйте множество виденных чисел.
❓Проверь себя
Почему словарный подход быстрее наивного перебора?
Что вернёт enumerate([10, 20, 30]) на втором шаге цикла?
ℹ️Важно
✅ Что вы узнали
Приём «запоминай виденное в словарь/множествоКоллекция уникальных элементов без порядка: {1, 2, 3}. По-английски set.» превращает медленный O(n²) перебор в быстрый O(n).
Для каждого числа ищется его «дополнение» target - x.
enumerate удобно даёт сразу индекс и значение.
Порядок «сначала проверь, потом запиши» критичен — иначе число может «найти само себя».
Комментарии
Загрузка…
Загрузка комментариев…