难度:简单
题目
有一堆石头,每块石头的重量都是正整数。
每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
如果 x == y,那么两块石头都会被完全粉碎;
如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0。
示例:
输入:[2,7,4,1,8,1]
输出:1
解释:
先选出 7 和 8,得到 1,所以数组转换为 [2,4,1,1,1],
再选出 2 和 4,得到 2,所以数组转换为 [2,1,1,1],
接着是 2 和 1,得到 1,所以数组转换为 [1,1,1],
最后选出 1 和 1,得到 0,最终数组转换为 [1],这就是最后剩下那块石头的重量。
题解
思路与算法:
因为每一回合都要选出最重的两块石头,我们自然而然地想到堆这个可以自动实现排序的数据结构。
将所有的石头放入到大顶堆中,然后依次取出最重的两块石头x和y,必有x ≥ y。如果x > y,则将新石头x - y放回到最大堆中;
如果x = y,两块石头完全被粉碎,因此不会产生新的石头。重复上述操作知道剩下的石头少于2块。
最终可能剩下 1 块石头,该石头的重量即为最大堆中剩下的元素,返回该元素;也可能没有石头剩下,此时最大堆为空,返回 0。
JS 实现:
var lastStoneWeight = function(stones) {
const pq = new MaxPriorityQueue();
for (const stone of stones) {
pq.enqueue('x', stone);
}
while (pq.size() > 1) {
const a = pq.dequeue()['priority'];
const b = pq.dequeue()['priority'];
if (a > b) {
pq.enqueue('x', a - b);
}
}
return pq.isEmpty() ? 0 : pq.dequeue()['priority'];
};
总结
为了弥补 JS 内置数据结构的缺失。除了 JS 内置数据结构之外,LeetCode 平台还对 JS 提供了两种额外的数据结构,它们分别是:
queue
priority-queue
这两个数据结构都使用的是第三方 datastructures-js 实现的版本
除了普通队列,LeetCode 还提供了一种特殊的队列 - 优先队列。
// empty queue with default priority the element value itself.
const numbersQueue = new MinPriorityQueue();
// empty queue, will provide priority in .enqueue
const patientsQueue = new MinPriorityQueue();
// empty queue with priority returned from a prop of the queued object
const biddersQueue = new MaxPriorityQueue({ priority: (bid) => bid.value });