有一堆石头,每块石头的重量都是正整数。
每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
如果 x == y,那么两块石头都会被完全粉碎; 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。 最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0。
解题思路
这一题简单的做法是将数组按降序排序,然后每次取2个数,做减法,如果结果不为0则将当前值重新插入到数组中,直到数组长度 < 2。
除了上述的方法,也可以通过大顶堆来实现,每次取2个最大数石头做减法,如果石头不为0则重新插入到堆中。
代码
class Heap {
constructor() {
this.data = [];
}
swap(i, j) {
[this.data[i], this.data[j]] = [this.data[j], this.data[i]]
}
compartor(i, j) {
return this.data[i] - this.data[j];
}
size() {
return this.data.length;
}
peek() {
if (!this.size()) return null;
return this.data[0]
}
offer(val) {
this.data.push(val);
this.bubbleUp(this.data.length-1);
}
pop() {
if (!this.size()) return null;
let res = this.data[0];
if (this.size() > 1) {
this.data[0] = this.data.pop();
this.bubbleDown(0);
} else {
this.data.pop();
}
return res;
}
bubbleUp(index) {
while(index) {
let parent = (index - 1) >> 1;
if (this.compartor(index, parent) > 0) {
this.swap(index, parent);
index = parent;
} else {
break;
}
}
}
bubbleDown(index) {
let last = this.data.length - 1;
while(index < last) {
let temp = index, left = index * 2 + 1, right = index * 2 + 2;
if (left <= last && this.compartor(left, temp) > 0) {
temp = left;
}
if (right <= last && this.compartor(right, temp) > 0) {
temp = right;
}
if (temp == index) break;
this.swap(temp, index);
index = temp;
}
}
}
var lastStoneWeight = function(stones) {
if (stones.length < 2) return stones[0] ? stones[0] : 0;
let h = new Heap();
for (i of stones) {
h.offer(i);
}
while(h.size() > 1) {
let x = h.pop();
let y = h.pop();
if (x !== y) h.offer(x-y);
}
if (!h.size()) return 0;
return h.peek()
};