为了尽可能多的石头被粉碎,每次找到重量最大的两个石头,比较重量,如果他们相等就都粉碎,如果不相等,会产生一块新的石头;然后再找到最大的两个,重新比较。。。
这里用最大堆。这篇文章有最小堆的实现解析 💁 最小堆。最大堆的实现思路基本一致,区别在于比较的时候,较大值会上升到堆顶。
代码:
let s = []
let len = 0
function push(el) {
s[len] = el
++len
if (len > 1) {
swim(len - 1)
}
}
function pop() {
if (len === 0) {
return null
}
const top = s[0]
if (len > 1) {
s[0] = s[len - 1]
sink(0, len - 1)
}
len--
return top
}
function peek() {
if (len === 0) {
return null
} else {
return s[0]
}
}
function sink(idx, lastIdx) {
while(idx <= lastIdx) {
const rightIdx = (idx + 1) * 2
const leftIdx = rightIdx - 1
if (leftIdx <= lastIdx) {
let valueIdx = leftIdx
if (rightIdx <= lastIdx && compare(valueIdx, rightIdx) < 0) {
valueIdx = rightIdx
}
if (compare(idx, valueIdx) < 0) {
swap(idx, valueIdx)
idx = valueIdx
} else {
break
}
} else {
break
}
}
}
function swim(idx) {
while(idx >= 0) {
let parent = (idx - 1) >> 1
if (compare(parent, idx) < 0) {
swap(parent, idx)
idx = parent
} else {
break
}
}
}
function swap(a, b) {
let temp = s[a]
s[a] = s[b]
s[b] = temp
}
function compare(a, b) {
return s[a] - s[b]
}
var lastStoneWeight = function(stones) {
// 这里可以使用类去实现,避免每次都得reset
s = []
len = 0
stones.forEach(push)
while(len > 1) {
const a = pop()
const b = pop()
if (a !== b) {
push(a - b)
}
}
return len > 0 ? s[0] : 0
};