Problem Statement in English

You’re given a list of stone weights - stones. Your task is to keep picking the 2 largest stones from that list, and smash them together until there’s either only 1 or no stones left, whilst following a few rules:

  • if the 2 stones have the same weight, then they’re both destroyed.
  • if the 2 stones have different weights, then you’re left with a stone that weighs the difference between the bigger and smaller one.

Approach

We need to maintain the stone weights in a max heap. That way, the 2 largest stones will always be at the top of the max heap.


Solution in Python


class Solution:
    def lastStoneWeight(self, stones: List[int]) -> int:
        for i in range(len(stones)):
            stones[i] *= -1
        heapq.heapify(stones)

        while len(stones) > 1:
            s1 = heapq.heappop(stones)
            s2 = heapq.heappop(stones)

            if s1 != s2:
                heapq.heappush(stones, -abs(-s1 - -s2))

        return -stones[0] if len(stones) == 1 else 0

Unfortunately, the nasty method to maintain the max heap makes the code a little ugly. We need to multiply all elements by $-1$ to have Python build a max heap instead of a min heap.


Complexity

  • Time: $O(n)$
    As that’s the time taken to build the max heap for $n$ elements.

  • Space: $O(n)$
    As we store $n$ stone weights at most in the max heap.


And we are done.