Back to blog
Apr 17, 2025
4 min read

Last Stone Weight

We have a collection of stones, each stone has a positive integer weight. Each turn, we choose the two heaviest stones and smash them together.

Difficulty: Easy | Acceptance: 66.50% | Paid: No Topics: Array, Heap (Priority Queue)

You are given an array of integers stones where stones[i] is the weight of the ith stone.

We are playing a game with the stones. On each turn, we choose the heaviest two stones and smash them together. Suppose the heaviest two stones have weights x and y with x <= y. The result of this smash is:

If x == y, both stones are destroyed, and If x != y, the stone of weight x is destroyed, and the stone of weight y has new weight y - x. At the end of the game, there is at most one stone left.

Return the weight of the last remaining stone, or 0 if there are no stones left.

Examples

Input: stones = [2,7,4,1,8,1]
Output: 1
Explanation: 
We combine 7 and 8 to get 1 so the array converts to [2,4,1,1,1] then,
we combine 2 and 4 to get 2 so the array converts to [2,1,1,1] then,
we combine 2 and 1 to get 1 so the array converts to [1,1,1] then,
we combine 1 and 1 to get 0 so the array converts to [1] then that's the value of the last stone.
Input: stones = [1,3]
Output: 1

Constraints

1 <= stones.length <= 30
1 <= stones[i] <= 1000

Approach 1: Sorting Simulation

Intuition Since we always need the two heaviest stones, we can repeatedly sort the array to access the largest elements at the end. After smashing them, we update the array and sort again.

Steps

  • Sort the array in ascending order.
  • While there is more than one stone:
    • Take the last two elements (y and x).
    • Remove them from the array.
    • If x != y, append (y - x) to the array.
    • Sort the array again.
  • Return the remaining stone or 0.
python
from typing import List

class Solution:
    def lastStoneWeight(self, stones: List[int]) -&gt; int:
        while len(stones) &gt; 1:
            stones.sort()
            y = stones.pop()
            x = stones.pop()
            if x != y:
                stones.append(y - x)
        return stones[0] if stones else 0

Complexity

  • Time: O(N² log N) — We sort up to N times.
  • Space: O(1) or O(N) depending on the sorting algorithm.
  • Notes: Simple to implement but inefficient for large inputs.

Approach 2: Max Heap (Priority Queue)

Intuition A Max Heap allows us to efficiently retrieve and remove the largest element in O(log N) time. This is optimal for repeatedly accessing the two heaviest stones.

Steps

  • Insert all stones into a Max Heap.
  • While the heap has more than one stone:
    • Pop the largest stone (y).
    • Pop the second largest stone (x).
    • If x != y, push (y - x) back into the heap.
  • Return the remaining stone or 0.
python
import heapq
from typing import List

class Solution:
    def lastStoneWeight(self, stones: List[int]) -&gt; int:
        # Python heapq is a min-heap, so we invert values to simulate a max-heap
        stones = [-s for s in stones]
        heapq.heapify(stones)
        
        while len(stones) &gt; 1:
            y = -heapq.heappop(stones)
            x = -heapq.heappop(stones)
            if x != y:
                heapq.heappush(stones, -(y - x))
                
        return -stones[0] if stones else 0

Complexity

  • Time: O(N log N) — Each heap operation takes O(log N).
  • Space: O(N) — To store the heap.
  • Notes: The most efficient approach for this problem.