Browse curriculum

Last Stone Weight

Smash the two heaviest stones until at most one is left, using a max-heap to find the heaviest pair each round.

Problem Understanding

Last Stone Weight: each turn, take the two heaviest stones y ≥ x and smash them. If they are equal both are destroyed; otherwise a stone of weight y − x is left. Repeat until at most one stone remains and return its weight, or 0.

Example: [2, 7, 4, 1, 8, 1] returns 1.

The Intuition: Always Ask for the Two Heaviest

The rules decide everything; the only question is how to find the two heaviest stones quickly, round after round, while new stones keep appearing.

Sorting once is not enough, because the new stone y − x can land anywhere. A max-heap is built for exactly this: pop the largest in O(log n), push any value in O(log n).

  1. Heapify all the stones.
  2. While at least two remain: pop y, pop x; if y != x, push y − x.
  3. Return the remaining stone, or 0.

Each round removes at least one stone, so there are at most n rounds.

Interactive Walkthrough

The heap's contents are listed heaviest first, which is the order it hands them out. Each round, the two stones popped appear in the smashed row with what they leave behind, and the new stone is highlighted where it lands.

Dry Run Table

Input: [2, 7, 4, 1, 8, 1]

Heap (heaviest first) y, x Result
8, 7, 4, 2, 1, 1 8, 7 push 1
4, 2, 1, 1, 1 4, 2 push 2
2, 1, 1, 1 2, 1 push 1
1, 1, 1 1, 1 both gone
1 — return 1

The Solution Template

A max-heap where the language has one. JavaScript has no built-in heap; with at most 30 stones, a sorted array does the same job.

Last Stone Weight Code
1var lastStoneWeight = function(stones) {
2 const heap = [...stones].sort((a, b) => a - b);
3 while (heap.length > 1) {
4 const y = heap.pop();
5 const x = heap.pop();
6 if (y !== x) {
7 const d = y - x;
8 const i = heap.findIndex((v) => v >= d);
9 heap.splice(i === -1 ? heap.length : i, 0, d);
10 }
11 }
12 return heap.length ? heap[0] : 0;
13};

Edge Cases & Common Mistakes

  • One stone: the loop never runs; return it.
  • Everything cancels: return 0 when the heap is empty, instead of reading heap[0].
  • Python's min-heap: forgetting to negate pops the lightest stones instead of the heaviest.
  • Sorting once at the start: the new stone y − x must go back in its place, or the next round picks the wrong pair.

Summary

Keep the stones in a max-heap. Pop the two heaviest, push back their difference if it is not zero, and repeat until at most one stone remains. O(n log n) time, O(n) space.

More practice: DSA interview questions with answers · patterns cheat sheet

The approach, step by step

  1. Build a max-heap

    Put every stone weight in a max-heap (negated values in Python).

  2. Smash the heaviest two

    While two or more stones remain, pop y and then x. If they differ, push y − x back.

  3. Return what is left

    Return the last stone's weight, or 0 if the heap is empty.

Frequently asked questions

Why use a heap for Last Stone Weight?

Every round needs the two heaviest stones, and the new stone can be any weight. A max-heap gives the largest in O(log n) and accepts the new stone in O(log n), so n rounds cost O(n log n) instead of re-sorting each time.


How do you get a max-heap in Python?

heapq is a min-heap, so store negated weights. The most negative value is the heaviest stone; negate again when you pop it and when you push the difference back.


What if two stones have equal weight?

Both are destroyed and nothing is pushed back. If every stone cancels out, the heap ends empty and the answer is 0.

Applying for software engineering roles? Free, no sign-up:

AI resume checker — match your resume to the job description