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 less than or equal to y. The result of this smash is:
x is destroyed, and the stone of weight y has new weight y - xAt the end of the game, there is at most one stone left. Return the weight of the last remaining stone. If there are no stones left, return 0.
Input: stones = [2,7,4,1,8,1]
Output: 1
Explanation:
Turn 1: Smash 8 and 7 → result = 1, stones = [2,4,1,1,1]
Turn 2: Smash 4 and 2 → result = 2, stones = [2,1,1,1]
Turn 3: Smash 2 and 1 → result = 1, stones = [1,1,1]
Turn 4: Smash 1 and 1 → result = 0, stones = [1]
Turn 5: Only one stone left, return 1
Input: stones = [1]
Output: 1
Input: stones = [2,2]
Output: 0
Explanation: Both stones are destroyed
We need to repeatedly find the two largest elements, which naturally suggests using a max-heap!
Process:
Why heap? Finding max in unsorted array is O(n), but heap gives us max in O(log n) and maintains ordering automatically.
This is a Max-Heap Simulation problem:
Python Note: Python's heapq is a min-heap, so negate values to simulate max-heap.
while len(heap) > 1:
first = heappop(heap) # Largest
second = heappop(heap) # Second largest
if first != second:
heappush(heap, first - second)
Java: Use PriorityQueue with reverse comparator for max-heap.
Time: O(n log n) where n = number of stones
Space: O(n)
Alternative: Sorting works but is O(n² log n) since we'd need to re-sort after each turn.
1import java.util.PriorityQueue;
2import java.util.Collections;
3
4class Solution {
5 public int lastStoneWeight(int[] stones) {
6 // Max-heap using reverse order comparator
7 PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
8
9 // Add all stones to heap
10 for (int stone : stones) {
11 maxHeap.offer(stone);
12 }
13
14 while (maxHeap.size() > 1) {
15 // Pop two heaviest stones
16 int first = maxHeap.poll(); // Largest
17 int second = maxHeap.poll(); // Second largest
18
19 // If different weights, push difference back
20 if (first != second) {
21 maxHeap.offer(first - second);
22 }
23 }
24
25 // Return last stone or 0 if all destroyed
26 return maxHeap.isEmpty() ? 0 : maxHeap.poll();
27 }
28}
29