Программа курса:
Разбор задачи: Вес оставшегося камня
Предложенный нами код решения:
import heapq
def lastStoneWeight(stones):
"""
Определяет вес последнего оставшегося камня после серии ударов.
:param stones: список целых чисел, представляющих веса камней
:return: вес последнего оставшегося камня или 0, если камней не осталось
"""
# Преобразуем веса камней в отрицательные числа для использования max-heap
stones = [-stone for stone in stones]
heapq.heapify(stones) # Создаем кучу
# Пока в куче больше одного камня
while len(stones) > 1:
# Достаем два самых тяжелых камня
stone1 = -heapq.heappop(stones) # Самый тяжелый
stone2 = -heapq.heappop(stones) # Второй самый тяжелый
# Если веса не равны, добавляем разницу обратно в кучу
if stone1 != stone2:
heapq.heappush(stones, -(stone1 - stone2))
# Возвращаем вес последнего камня или 0, если куча пуста
return -stones[0] if stones else 0
Модуль heapq предоставляет функции для работы с минимальными кучами (min-heap). В контексте задачи минимальная куча используется для эффективного извлечения двух самых тяжелых камней, но с некоторыми модификациями.
Шаги работы с heapq:
Преобразование массива в минимальную кучу:
stones = [-stone for stone in stones] heapq.heapify(stones)Так как
heapqработает с минимальными кучами, а нам требуется доступ к максимальным значениям, веса камней преобразуются в отрицательные числа (-stone). После этого массив превращается в кучу с помощьюheapq.heapify.Например, если
stones = [2, 7, 4, 1, 8, 1], после преобразования массив станет[-2, -7, -4, -1, -8, -1], а послеheapifyэто станет минимальной кучей:[-8, -7, -4, -1, -2, -1].Извлечение двух самых тяжелых камней:
stone1 = -heapq.heappop(stones) stone2 = -heapq.heappop(stones)Функция
heapq.heappopизвлекает наименьший элемент из кучи, но так как элементы отрицательные, это фактически эквивалентно извлечению самого тяжелого камня. Извлеченные веса возвращаются в положительном виде с помощью-.Например, если куча
[-8, -7, -4, -1, -2, -1], то первый вызовheappopвернет-(-8) = 8, а второй вызов —-(-7) = 7.Добавление разницы обратно в кучу:
if stone1 != stone2: heapq.heappush(stones, -(stone1 - stone2))Если два камня имеют разный вес, их разница (в положительном виде) преобразуется обратно в отрицательное значение и добавляется в кучу с помощью
heapq.heappush.Например, если
stone1 = 8иstone2 = 7, их разница8 - 7 = 1. В куче это будет добавлено как-1.Проверка остатка камней:
return -stones[0] if stones else 0Если в куче остался один элемент, он возвращается как последний оставшийся камень. Если куча пуста, возвращается
0.
Преимущества использования heapq:
- Эффективность: Операции извлечения (
heappop) и вставки (heappush) работают за логарифмическое время, что делает подход с кучей более производительным по сравнению с повторной сортировкой списка на каждом шаге. - Простота работы с приоритетами: Использование отрицательных чисел позволяет легко адаптировать минимальную кучу для работы с максимальными элементами.
Итог:
Использование heapq позволяет эффективно управлять процессом обработки самых тяжелых камней. Этот подход удобен, если необходимо минимизировать количество операций сортировки и достичь оптимальной производительности для задач с большим количеством камней.