Last Stone Weight easy
Problem Statement
You are given an array of integers stones
where stones[i]
is the weight of the i
th 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 <= y
. The result of this smash is:
- If
x == y
, both stones are destroyed. - If
x != y
, the stone of weightx
is destroyed, and the stone of weighty - x
is added to the array.
The game ends when there is at most one stone left. Return the weight of the last remaining stone.
Example 1
Input: stones = [2,7,4,1,8,1] Output: 1 Explanation:
- We smash 8 and 7, and the remaining stones are [2,4,1,1,1].
- We smash 4 and 2, and the remaining stones are [1,1,1,1].
- We smash 1 and 1, and the remaining stones are [1,1].
- We smash 1 and 1, and the remaining stones are [].
- The last stone is 1.
Example 2
Input: stones = [1] Output: 1
Steps to Solve
- Use a Priority Queue (Max Heap): A max heap is ideal because we need to efficiently find the two largest stones at each step. Java's
PriorityQueue
with a custom comparator provides this functionality. - Iterative Smashing: While the priority queue contains more than one stone, repeatedly:
- Remove the two largest stones (
x
andy
). - If
x != y
, addy - x
back to the queue.
- Remove the two largest stones (
- Return the Last Stone: After the loop, if the queue is not empty, the remaining stone is the answer; otherwise, it's 0.
Explanation
The priority queue keeps track of the stones in descending order of weight. By repeatedly removing the two largest stones and either destroying them or replacing them with a smaller stone, we simulate the game's mechanics. The use of a max heap ensures that the heaviest stones are always processed first, making the algorithm efficient.
Code
import java.util.PriorityQueue;
class Solution {
public int lastStoneWeight(int[] stones) {
PriorityQueue<Integer> pq = new PriorityQueue<>( (a, b) -> b - a); // Max heap
// Add stones to the priority queue
for (int stone : stones) {
pq.offer(stone);
}
// Simulate smashing stones
while (pq.size() > 1) {
int y = pq.poll();
int x = pq.poll();
if (x != y) {
pq.offer(y - x);
}
}
// Return the weight of the last stone (or 0 if no stones left)
return pq.isEmpty() ? 0 : pq.poll();
}
}
Complexity
- Time Complexity: O(N log N), where N is the number of stones. This is dominated by the
offer
andpoll
operations of the priority queue, which take O(log N) time each. We perform these operations at most 2N times. - Space Complexity: O(N) to store the priority queue. In the worst case (all stones are distinct), the queue will hold all stones at once.