1046. Last Stone Weight
## description
## 1046. Last Stone Weight
You are given an array of integers stones where stones[i] is the weight of the ith 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, and
- –If x != y, the stone of weight x is destroyed, and the stone of weight y has new weight y - x.
At the end of the game, there is at most one stone left.
Return the weight of the last remaining stone. If there are no stones left, return 0.
Example 1:
1Input: stones = [2,7,4,1,8,1]
2Output: 1
3Explanation:
4We combine 7 and 8 to get 1 so the array converts to [2,4,1,1,1] then,
5we combine 2 and 4 to get 2 so the array converts to [2,1,1,1] then,
6we combine 2 and 1 to get 1 so the array converts to [1,1,1] then,
7we combine 1 and 1 to get 0 so the array converts to [1] then that's the value of the last stone.Example 2:
1Input: stones = [1]
2Output: 1- –1 <= stones.length <= 30
- –1 <= stones[i] <= 1000
Constraints:
## notes
### Intuition
We want to grab the two largest stones on every iteration.
### Implementation
To efficiently grab the two largest stones on every iteration, we can use a max heap.
Start by initializing our max heap. In Python, the standard heap is a min heap so we can negate each value to make it a max heap.
Next, we iterate while the max heap has at least 2 elements:
- –Pop the two largest elements off the max heap, x and y (must be negated to get the actual values)
- –If x > y, swap them
- –If x == y, continue to the next iteration, no new stones added (both destroyed)
- –Otherwise, add y-x to the heap (must be negated to maintain max heap property)
When the iteration completes, we either have 1 or 0 elements in the max heap, return the element or 0 if its empty.
### Edge-cases
Remember to negate when adding and negate when popping from the heap to ensure the max heap property is satisfied and we are comparing the actual stone values.
- –Time: O(n log n), we iterate over all stones once and in each iteration we are popping from the heap which is O(log n).
- –Space: O(n), the max heap will start with all elements.
### Complexity
## solution
1from typing import List
2import heapq
3
4class Solution:
5 def lastStoneWeight(self, stones: List[int]) -> int:
6 max_heap = []
7 for stone in stones:
8 heapq.heappush(max_heap, -stone)
9
10 while len(max_heap) > 1:
11 x, y = -heapq.heappop(max_heap), -heapq.heappop(max_heap)
12 if x > y:
13 x, y = y, x
14 if x == y:
15 continue
16 else:
17 heapq.heappush(max_heap, -(y-x))
18
19 return -max_heap[0] if max_heap else 0
20
21
22
23if __name__ == "__main__":
24 # Include one-off tests here or debugging logic that can be run by running this file
25 # e.g. print(solution.two_sum([1, 2, 3, 4], 3))
26 solution = Solution()
27