41. Last Stone Weight
Each turn, smash the two heaviest stones together. If they weigh the same both are destroyed; otherwise the lighter one is destroyed and the heavier loses that much weight.
Return the weight of the last stone, or 0 if none are left.
Example 1
stones = [2,7,4,1,8,1]1Example 2
stones = [1]1Hint 1
You repeatedly need the two largest values: a max-heap gives them in O(log n).
Approach 1: Sort every turn
Re-sort after each smash.
Approach 2: Max-heap ✅
Pop two, push the difference.
Reference solution for Max-heap (time O(n log n), space O(n)). Each solution passes every test in all four languages.
class Solution:
def lastStoneWeight(self, stones: List[int]) -> int:
heap = [-s for s in stones] # Python has a min-heap: store negatives for a max-heap
heapq.heapify(heap)
while len(heap) > 1:
a, b = -heapq.heappop(heap), -heapq.heappop(heap)
if a != b:
heapq.heappush(heap, -(a - b))
return -heap[0] if heap else 0class Solution {
public int lastStoneWeight(int[] stones) {
PriorityQueue<Integer> heap = new PriorityQueue<>(Collections.reverseOrder());
for (int s : stones) heap.offer(s);
while (heap.size() > 1) {
int a = heap.poll(), b = heap.poll();
if (a != b) heap.offer(a - b);
}
return heap.isEmpty() ? 0 : heap.peek();
}
}class Solution {
public:
int lastStoneWeight(vector<int>& stones) {
priority_queue<int> heap(stones.begin(), stones.end()); // max-heap
while (heap.size() > 1) {
int a = heap.top(); heap.pop();
int b = heap.top(); heap.pop();
if (a != b) heap.push(a - b);
}
return heap.empty() ? 0 : heap.top();
}
};class MinHeap {
constructor(less = (a, b) => a < b) { this.a = []; this.less = less; }
get size() { return this.a.length; }
peek() { return this.a[0]; }
push(x) { const a = this.a; a.push(x); let i = a.length - 1;
while (i > 0) { const p = (i - 1) >> 1; if (!this.less(a[i], a[p])) break; [a[i], a[p]] = [a[p], a[i]]; i = p; } }
pop() { const a = this.a, top = a[0], last = a.pop();
if (a.length) { a[0] = last; let i = 0;
while (true) { const l = 2 * i + 1, r = l + 1; let m = i;
if (l < a.length && this.less(a[l], a[m])) m = l;
if (r < a.length && this.less(a[r], a[m])) m = r;
if (m === i) break; [a[i], a[m]] = [a[m], a[i]]; i = m; } }
return top; }
}
function lastStoneWeight(stones) {
const heap = new MinHeap((a, b) => a > b); // max-heap
for (const s of stones) heap.push(s);
while (heap.size > 1) {
const a = heap.pop(), b = heap.pop();
if (a !== b) heap.push(a - b);
}
return heap.size ? heap.peek() : 0;
}Try solving it yourself first. Interviewers care more about how you explain the approach than about the finished code.
Watch the core idea of this problem step by step. Change the input and press Visualize.
Explained in the lesson Heaps & Priority Queues.
Run your code to see results here.