Разбор задачи: Вес оставшегося камня

Предложенный нами код решения:

 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:

  1. Преобразование массива в минимальную кучу:

    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].

  2. Извлечение двух самых тяжелых камней:

    stone1 = -heapq.heappop(stones)
    stone2 = -heapq.heappop(stones)
    

    Функция heapq.heappop извлекает наименьший элемент из кучи, но так как элементы отрицательные, это фактически эквивалентно извлечению самого тяжелого камня. Извлеченные веса возвращаются в положительном виде с помощью -.

    Например, если куча [-8, -7, -4, -1, -2, -1], то первый вызов heappop вернет -(-8) = 8, а второй вызов — -(-7) = 7.

  3. Добавление разницы обратно в кучу:

    if stone1 != stone2:
        heapq.heappush(stones, -(stone1 - stone2))
    

    Если два камня имеют разный вес, их разница (в положительном виде) преобразуется обратно в отрицательное значение и добавляется в кучу с помощью heapq.heappush.

    Например, если stone1 = 8 и stone2 = 7, их разница 8 - 7 = 1. В куче это будет добавлено как -1.

  4. Проверка остатка камней:

    return -stones[0] if stones else 0
    

    Если в куче остался один элемент, он возвращается как последний оставшийся камень. Если куча пуста, возвращается 0.


Преимущества использования heapq:

  1. Эффективность: Операции извлечения (heappop) и вставки (heappush) работают за логарифмическое время, что делает подход с кучей более производительным по сравнению с повторной сортировкой списка на каждом шаге.
  2. Простота работы с приоритетами: Использование отрицательных чисел позволяет легко адаптировать минимальную кучу для работы с максимальными элементами.

Итог:

Использование heapq позволяет эффективно управлять процессом обработки самых тяжелых камней. Этот подход удобен, если необходимо минимизировать количество операций сортировки и достичь оптимальной производительности для задач с большим количеством камней.

 



Вы должны Войти или Зарегистрироваться чтобы оставлять комментарии