Представьте очередь людей. Для каждого человека вы хотите узнать «сколько всего людей вокруг него» — это все слева от него плюс все справа. Вместо того чтобы для каждого заново пересчитывать всю очередь, вы делаете два прохода: один раз идёте слева направо, накапливая «сколько было слева», и один раз справа налево, добавляя «сколько справа».
Та же идея с произведениями: ответ для позиции i — это (произведение всех слева) × (произведение всех справа). Деление не нужно.
Условие
Дан списокИзменяемая упорядоченная коллекция элементов: [1, 2, 3]. По-английски list.nums. Верните список res, где res[i] — произведение всех элементов, кроме nums[i]. Делением пользоваться нельзя, цель — O(n).
Пример: [1, 2, 3, 4] → [24, 12, 8, 6].
Идея: префиксы и суффиксы
Для каждого i ответ = (произведение всех слева от i) × (произведение всех справа от i). Считаем за два прохода: сначала накапливаем произведение слева направо, потом домножаем на произведение справа налево.
▶ product-except-self.py
Как это работает на [1, 2, 3, 4]
Первый проход (префиксы): в res[i] кладём произведение всего, что слева от i. Получаем [1, 1, 2, 6] (для индексаНомер позиции элемента в последовательности. В Python нумерация с нуля: первый элемент — индекс 0. 0 слева ничего — 1).
Второй проход (суффиксы), справа налево: домножаем res[i] на произведение всего, что справа. Для индекса 3 справа ничего (×1), для индекса 2 ×4, и так далее.
Итог: [24, 12, 8, 6]. Каждый элемент — «слева × справа», что и есть «всё, кроме себя».
📝Заметка
range(n - 1, -1, -1) идёт по индексам в обратную сторону: от последнего к нулевому. Шаг -1, правая граница -1 не включается, поэтому 0 попадает. Полезный приём для проходов «справа налево».
💡Совет
🔮 Предскажите вывод
В примере есть ноль: что вернёт product_except_self([3, 0, 2])? Подумайте: для позиции самого нуля произведение «всех кроме него» = 3×2, а для остальных в произведение войдёт ноль.
▶ predict-product.py
Ответ — [0, 6, 0]. Для индекса 0 в произведение «всех кроме» входит ноль → 0. Для индекса 1 (сам ноль) — это 3×2 = 6. Для индекса 2 снова входит ноль → 0. Этот приём корректно работает с нулями, в отличие от подхода «перемножить всё и поделить».
⚠️ Частые ошибки новичков
Соблазнительное «лёгкое» решение — перемножить весь список и делить на nums[i]. Оно запрещено условием и ломается на нулях: деление на ноль вызовет ZeroDivisionError. Запустите сломанный код и убедитесь, почему префиксы/суффиксы надёжнее.
▶ broken-product.py
Заданиесредняярешение.py
Реализуйте product_except_self(nums) за O(n) без деления, через префиксные и суффиксные произведения.
Заданиелёгкаярешение.py
Дополнительное упражнение на префиксы. Напишите running_sum(nums), которая возвращает список «нарастающих сумм»: res[i] = сумма всех элементов от начала до i включительно. Пример: [1, 2, 3, 4] → [1, 3, 6, 10].
❓Проверь себя
Чему равен ответ res[i] в задаче «произведение, кроме себя»?
Что делает range(n - 1, -1, -1)?
ℹ️Важно
✅ Что вы узнали
Префиксные и суффиксные произведения решают задачу за O(n) без деления.
Подход устойчив к нулям, в отличие от «перемножить всё и поделить».
range(n-1, -1, -1) — стандартный способ пройти список справа налево.
Комментарии
Загрузка…
Загрузка комментариев…