150NeetCode 150

65.Last Stone Weight

EasyHeap / Priority Queue · 2/7

Problem

You have an array stones where stones[i] is the weight of the i-th stone. Each turn, take the two heaviest stones x <= y and smash them:

  • If x == y, both are destroyed.
  • If x != y, x is destroyed and y becomes y - x.

Repeat until at most one stone remains. Return its weight, or 0 if none remain.

Examples

Input:  stones = [2,7,4,1,8,1]
Output: 1
Explanation: smash 7,8 -> 1 => [2,4,1,1,1]; smash 2,4 -> 2 => [2,1,1,1];
             smash 2,1 -> 1 => [1,1,1]; smash 1,1 -> 0 => [1]. Answer 1.
Input:  stones = [1]
Output: 1
Input:  stones = [3,3]
Output: 0
Explanation: Equal stones destroy each other.

Constraints

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

💡 Key Insight

Every turn needs the current two largest values, and the remainder y - x is put back into the pool. A max-heap supports exactly that: two polls and at most one offer, each O(log n), instead of re-sorting the whole array every turn.

Brute Force (Sort Every Turn)

TimeO(n² log n)SpaceO(n)

Intuition

Keep the stones in a list, sort it each turn, and take the last two. Simulate literally.

Algorithm

  1. Put the stones into a list.
  2. While the list has more than one stone: sort it, remove the last two y and x, and if y != x add y - x.
  3. Return the remaining stone or 0.

Visualization

[2,7,4,1,8,1] sort -> [1,1,2,4,7,8] take 8,7 -> add 1
[1,1,2,4,1]   sort -> [1,1,1,2,4]   take 4,2 -> add 2
[1,1,1,2]     sort -> [1,1,1,2]     take 2,1 -> add 1
[1,1,1]                             take 1,1 -> nothing
[1] -> 1

Code

java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Solution {
    public int lastStoneWeight(int[] stones) {
        List<Integer> list = new ArrayList<>();
        for (int s : stones) {
            list.add(s);
        }
        while (list.size() > 1) {
            Collections.sort(list);
            int y = list.remove(list.size() - 1); // heaviest
            int x = list.remove(list.size() - 1); // second heaviest
            if (y != x) {
                list.add(y - x);
            }
        }
        return list.isEmpty() ? 0 : list.get(0);
    }
}

Complexity

  • Time: O(n² log n) — up to n turns, each with an O(n log n) sort.
  • Space: O(n) — the list.

Complexity Comparison

Approach Time Space
Sort Every Turn O(n² log n) O(n)
Sorted List + Binary Insertion O(n²) O(n)
Max-Heap O(n log n) O(n)

Common Pitfalls

  • Using Java's default PriorityQueue, which is a min-heap — you would smash the two lightest stones.
  • Returning heap.peek() without checking for an empty heap (all stones may cancel out, e.g. [3,3]).
  • Pushing 0 back when the stones are equal — harmless for the answer but wrong semantics and extra turns; only push when y > x.
  • Computing x - y (negative) after polling in the wrong order.