Smash the two heaviest stones this round
first · y
vs
second · x
→
y − x
stones heap tree shows weights · max at the root
stones list what the PriorityQueue really stores: negated weights, smallest (= heaviest) at index 0
Rounds
public int lastStoneWeight(int[] stones) { List<Integer> list = new ArrayList<>(); for (int s : stones) { list.add(-s); // max-heap trick } PriorityQueue<Integer> heap = new PriorityQueue<>(list); // heapify while (heap.size() > 1) { int first = heap.poll(); // heaviest int second = heap.poll(); // next heaviest if (second > first) { heap.offer(first - second); } } heap.offer(0); return Math.abs(heap.peek());}
- first
- —
- second
- —
- heap.size()
- —
- heap
- []
Why it works
- Brute force re-sorts: sort, smash the last two, insert the remainder, sort again. O(n² log n), or O(n²) with careful insertion.
- A max-heap hands out the heaviest stone in O(log n) and takes a new one back in O(log n). At most n − 1 rounds: O(n log n) overall.
- Java's
PriorityQueueis a min-heap by default, so store −weight. (ACollections.reverseOrder()comparator also works, but the heapify constructor does not take one.) The most negative value is the heaviest stone, andfirst - secondis the negated remainder, ready to push. - Pitfall: with negatives the comparison flips.
second > firstmeans the second stone is lighter, so something is left. Equal stones push nothing. - Line 14: offering 0 makes
heap.peek()safe when every stone vanished: on an empty heap it returnsnull, and unboxing that throwsNullPointerException. It replaces a separate empty check. - Related: Kth Largest Element in an Array (LeetCode 215) and K Closest Points (973) use the same
PriorityQueuepatterns.